Shrike
Shrike

Reputation: 9500

CSS: layout DL as flexible table with paddings

I want to use DL/DT/DD approach to organize my forms. I need to structure them as tables (a column for label and a column for value). The following html+css works fine but till I add margin or padding to dt and/or dd.

<html><head>
<style>
dl {
  width: 100%;
  overflow:hidden;
}

dt {
  float: left;
  width: 50%;
  margin: 0px;
  padding: 0px;
}
dd {
  float: left;
  width: 50%;
  margin: 0px;
  padding: 0px;
}
</style></head>
<body>
<dl>
  <dt>first name</dt>
  <dd><input />
</dl>
</body></html>

If I replace "margin: 0px" in dt's style with "margin: 5px" or the same for padding then dd element jumps on next row.

I need:

How to add margin/padding and keep relative widths (50%/50%)?

p.s. I've seen many similar questions about DL and table layout, but my question about combination of dl + table layout + relative widths + paddings. I can get it working with relative widths or paddings but not both.

Upvotes: 0

Views: 1928

Answers (5)

gilly3
gilly3

Reputation: 91527

All you need is to specify the magical property: box-sizing: border-box. You can then use padding all you want without increasing the width.

JSFiddle Demo

See also: box-sizing support in ie7

box-sizing addresses padding and borders, but not margins. If you want to use margin as well, use calc() to subtract the margin from the width. For example, if you want a 5px left margin:

dd {
    margin: 0 0 0 5px;
    width: calc(50% - 5px);
}

But, calc() does not work in IE8 or earlier.

more on calc()

Upvotes: 1

pflangan
pflangan

Reputation: 21

You just need to make sure that each dt clears the previous alignment;

add

dt {
    clear:both;
}

to the css defined above

see http://jsfiddle.net/Nd2sH/

Upvotes: 1

yunzen
yunzen

Reputation: 33439

I found a solution now (under the shower!)

Give the outer DL display:block and some padding to the left and right that add up to the margins and padding the DT and DD. Now the 100% of the DL are the basis for the 50% of the inner elements. Now give these your desired margins and paddings. Until now it won't work as desired. Yet there's things still to come. Add up all the margins and paddings of the DT and the DDrespectively. And give each a negative margin (the DT to the left and the DD to the right) so all the margins and paddings of them add up to zero/naught/niente/nada. E Voilà! Now you can have any combination of percentage you want, e.g. 30% - 70%.

dl {
    display: block;
    overflow:hidden;
    padding: 5px 15px 5px 20px;

}

/* the -15px in the margin is to compensate for the 5px in the margin and the 2 x 5px in the padding */
dt {
    float: left;
    width: 30%;
    margin: 0px 5px 0 -15px;
    padding: 5px;
    background: yellow;
}
/* the -10px in the margin is to compensate for the 2 x 5px in the padding */
dd {
    float: left;
    width: 70%;
    margin: 0px -10px 0 0px;
    padding: 5px;
    background: yellow;
}

http://jsfiddle.net/HerrSerker/AADG7/

Upvotes: 1

yunzen
yunzen

Reputation: 33439

The only things about it you can do:

Use JavaScript to get the width of the DL and then calculate the width of the DT and the DD so that the width of these plus the margin and the padding add up to the 100% of the DL

Or set a fixed width for the first column and no width for the second

Or wrap the content of each DT and DD with a DIV and give this the margin and padding

Upvotes: 0

Brian Hoover
Brian Hoover

Reputation: 7991

I would use nested DIVs or spans, inside the and elements. Right now, the 50% width is conflicting with the need for a padding or a margin.

Something like this would accomplish the same thing.

  <dt><div style="margin:5px;">first name</div></dt>
  <dd><div style="margin:5px;"><input /></div></dd>

Upvotes: 0

Related Questions