1

So I have three divs and I would like all three of them to take up the full width of their container and have a specific margin between them.

<div class="container">
    <div class="foo">
        content
    </div>
    <div class="foo">
        bit more content
    </div>
    <div class="foo>
        Very much more content
    </div>
</div>

And my CSS looks something like:

.foo { 
   width: 31%; 
   margin-left: 10px;
}
.foo:first-child { 
   margin-left: 0px;
}

However, with this set up the divs will wrap when the page gets too small and the divs will not stretch to the edge when the page is too big.

Is there an easy way to have a CONSTANT margin between them (no 'margin-left: 3%') yet still have the three divs stretch evenly across no matter the size of the page?

EDIT From the first answer, I took the idea of putting the padding inside of the div making it accounted for as part of the width and modified it a bit to use css that is more fully supported across all browsers.

So as long as the container of the three divs remains greater than 120px, the spacing between the divs in this example will always be a constant 16px. Also, no matter the size of the outer container, the inside divs will always take up the entire width of the three containers.

Example: http://jsfiddle.net/U8U7D/5/

Steven Rogers
  • 1,874
  • 5
  • 25
  • 48
  • 2
    Question, Cap, are you trying to get all 3 `div` blocks on the same line? Regardless, you could try adding padded containers around each one that use `box-sizing:border-box`. A *hard* padding on the containers will then be incorporated into the width -- which each `div` can inherit. – Casey Falk Jul 18 '14 at 19:26
  • I would use that route, but my project is dependent on working well across as many browsers as possible. So http://caniuse.com/css3-boxsizing is probably not going to cut it. Thanks though. – Steven Rogers Jul 18 '14 at 19:29
  • I'm using the background in those, but now I think about it, I could probably nest the background inside the padding. (YES they are on the same line, forgot to mention that.) P.S. Thanks for calling me Cap, not sarcastic, I love it when people call that out! – Steven Rogers Jul 18 '14 at 19:31
  • I couldn't resist; I'm reading the comics atm lol. ANYWAY. I would say that supporting back to IE8 is sufficient for nearly anything today. Do you expect – Casey Falk Jul 18 '14 at 19:33
  • It's good to see the Captain taking up web programming. – 2540625 Jul 19 '14 at 08:30

2 Answers2

1

You could try adding a padded container around each div that uses box-sizing:border-box and position:relative. A hard padding on these containers will then be incorporated into the max-width that each div will inherit. Thus, you could specify some constant "margin" (or rather, "parent padding") and still have the divs stretch evenly.

In terms of browser support, I would argue that box-sizing:border-box is fine (source). Chris has a good blog post on it. (The alternative would be writing a JavaScript function that re-calculated the width from the padding and border -- so you're really just saving yourself a headache.)

Here's some sample HTML describing what I mean:

<div class="container">
    <div class="fooContainer">
        <div class="foo">content</div>
    </div>
    <div class="fooContainer">
        <div class="foo">bit more content</div>
    </div>
    <div class="fooContainer">
        <div class="foo">
           Very much more content
        </div>
    </div>
</div>

Here is the commented CSS explaining what is going on:

.fooContainer {
    width: 30%;
    position: relative; /* Restrain children max-widths to this width. */
    display: inline-block; /* "Show divs on the same line." */
    box-sizing:border-box; /* Include padding+border in width calculation. */
    padding: 0px 40px;  /* Just an example padding. */
}

Example Fiddle

NOTE: In terms of responsiveness, the page scales appropriately until you reach the point where the text literally just can't fit; you could fix that be just letting the containers overflow or by setting some minimum width -- but I leave that design choice to you.

Casey Falk
  • 2,617
  • 1
  • 18
  • 29
  • I really cannot use non-fully supported css in the project I'm working on, but tweaking your design I came up with this: http://jsfiddle.net/U8U7D/2/ It uses the same concept of having the padding being incorporated into the width, but two major differences: 1, the elements now go all the way to the sides and 2, all of the css used is used across almost all browsers. – Steven Rogers Jul 18 '14 at 19:56
  • Fair enough -- if that solves your problem, good work. :) I will remark that your `div` elements won't be centered -- but perhaps that is by design. Anyway, "... you should accept the answer that you found to be the most helpful to you, personally" (http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work). Whatever works. – Casey Falk Jul 18 '14 at 20:04
  • Forgot to hit update when I copied the link, here is what I'm talking about: http://jsfiddle.net/U8U7D/3/ – Steven Rogers Jul 18 '14 at 20:05
  • Ahhh! I see. Good work! I had assumed you wanted it to scale with the page; I've been doing too much responsive design lately. ;) – Casey Falk Jul 18 '14 at 20:07
  • It's going to scale with the page to an extent. I don't plan on this going smaller than 320px, and I DO plan on this becoming horizontal divs at around 600px. heh, probably should have mentioned that. I just want it to go from edge to edge of the screen with constant 20px between the divs from 600px upwards. – Steven Rogers Jul 18 '14 at 20:11
  • Should have mentioned that in your question. ;) You'll want to use a media query for that (/developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries). – Casey Falk Jul 18 '14 at 20:13
  • I do know about media queries and how to use them, my question lies from 600px upwards. – Steven Rogers Jul 18 '14 at 21:43
  • Check out the 2nd answer here: http://stackoverflow.com/questions/15977118/change-css-class-if-window-is-less-than . You can just specify different CSS when the viewport is greater then 600px. – Casey Falk Jul 18 '14 at 21:47
  • Not quite sure if you fully read my last comment. I do know how to use media queries. I do know how to set css conditionals and how they interact. My question was not how to make the three divs go from inline to stacked vertically, it was how do I keep a constant space between them as their container grows or shrinks. I found a way to solve my problem using the tools that I am limited to and I'm happy with it. No questions left to be answered, no resources to be had. Unless you can send me a coupon for a free cookie, I have nothing else I can ask for. – Steven Rogers Jul 18 '14 at 22:15
  • Er... your comment says "[your] question lies from 600px onward." I must have misunderstood what you meant. I took that to mean you didn't understand how to apply media queries for widths (this being a separate point from your original question altogether). Anyways... Regardless, if you're happy I'm happy. No cookies -- sorry, Cap. Laters. :) – Casey Falk Jul 18 '14 at 22:19
  • Sure thing, @JonathanDrapeau. Since his *other* "question" object had an `a` field and his code tried accessing that field, I had assumed that it was a copy-paste error (however his recent comment explains that is not the case). I agree that it is good for question authors to fix their own code, but not at the expense of the question. I went to revert the change to the original (and then noticed you had -- thanks), but note that the author just un-reverted your change. So, all is well. Thanks for letting me know. – Casey Falk Jul 21 '14 at 12:40
1

Tables solution: http://jsfiddle.net/h29JS/ (will work in old browsers).

.container {
    display: table;
    width: 100%;
}

.container > div {
    display: table-cell;
    width: 33.3%;
    outline: 1px solid red;
}

.container > div + div {
    padding-left: 10px;
}

Flexbox solution: http://jsfiddle.net/gmcjw/.

.container {
    display: -webkit-flex;
    display: fex;
    -webkit-flex-direction: row;
    flex-direction: row;
}

.container > div {
    -webkit-flex: 1 1 33%;
    outline: 1px solid red;
}

.container > div + div {
    margin-left: 10px;
}

Floating solution: http://jsfiddle.net/4w85y/ (will work in older browsers also).

* {
    box-sizing: border-box;
}

/* 
    This is used to prevent margin collapse 
    due to floating
*/

.container {
    display: table;
    width: 100%;
}

.container > div {
    float: left;
    width: 33.3%;
    outline: 1px solid red;
}

.container > div + div {
    padding-left: 10px;
}

Lastly, another newer approach using columns: http://jsfiddle.net/4G5E9/ (can be a bit buggy).

* {
    box-sizing: border-box;
}

.container {
    width: 100%;
    -webkit-column-count: 3;
    -moz-column-count: 3;
    column-count;

    -webkit-column-gap: 10px;
    -moz-column-gap: 10px;
    column-gap: 10px;
}

.container > div {
    display: inline-block;
    width: 100%;
    border: 1px solid red;
}
DRD
  • 5,557
  • 14
  • 14
  • +1 multiple approaches. But tables?... *shudders* (http://stackoverflow.com/questions/313468/why-is-using-tables-for-website-layout-such-an-evil) – Casey Falk Jul 18 '14 at 20:08
  • Also a quick note that `flexbox` is *not* very well supported (needs IE10+) (http://caniuse.com/flexbox). – Casey Falk Jul 18 '14 at 20:10
  • There is nothing wrong with using tables. Tables are blocks that srinkwrap their contents, which is very useful for horizontal centering. When elements are floated within a table, the table's margins do not collapse. When you want to create elements of equal height, setting their container to table and them to table-cell will get that done. Tables have a lot of benefits and a web developer should not be a prude and, instead, use what tools do the job best. Having this dogma that tables are evil is just stupid, especially since tables are easily declared from within CSS. – DRD Jul 18 '14 at 20:26
  • Geez -- no need to attack, bud. Making a mild joke (did you even look at the link?). Anyway, there actually ARE some penalties for using tables: (1) they are hard for readers and crawlers which can be an issue for people who need to use them; (2) they were designed for tabular content -- like the `` tag is for code or the `

    ` tag is for paragraphs; and, they can become "deeply-nested" messes if you resort to them when you really just need `div` tags. ANYWAYS... Sorry for being "prudent." :(

    – Casey Falk Jul 18 '14 at 20:33
  • Not trying to deny that they are useful -- but it is best to be aware of the consequences when presented with a nice palette of choices (complement). – Casey Falk Jul 18 '14 at 20:35
  • Sure did. The question and the answers for that post go back to 2008. And, yes, in the good old days, tables, as a markup, were used for layouts. Heck, I even used them myself. That is a bad practice. However, notice, for this question, I did not change markup - it is still divs within divs. But from within CSS, in a targeted fashion, the browser is told to treat the `.container` as a table with all the beautiful consequences. So, give tables a proper place in your arsenal of tools. And, don't take my comments too seriously. It's meant to be a nice information exchange. Cheers. – DRD Jul 18 '14 at 20:44