5

Is there an easy way to distribute inline elements within a parent block container using CSS? Setting margins to auto doesn't work since the margins between inline elements are set to 0 and I don't want to mess around with percentages as the content is dynamic.

In particular, I have several anchor elements (a) within a paragraph (p) that spans 80% of its container and I'm looking for an easy way to distribute them evenly within the paragraph.

EDIT (@cletus): The paragraph will not wrap and the anchors are the only thing in the paragraph. By distribute evenly, I mean that the space between the left (right) edge and first (last) element and the elements themselves is equidistant.

gvkv
  • 1,894
  • 2
  • 22
  • 34
  • Can you clarify what you mean by distribute evenly? Are these links the only thing in the paragraph? Does the paragraph wrap line? – cletus Mar 02 '09 at 02:43
  • 1
    using "text-align: justify" can be made to work by adding a dummy inline-block `
    ` set to 100% width and 0px height. [Here is a jsfiddle showing the effect](http://jsfiddle.net/Pointy/XSKqx/) - I haven't started trying IE yet.
    – Pointy Apr 15 '11 at 15:44
  • @Pointy, that's pretty cool although I still maintain that it shouldn't be necessary. Thanks for the solution though. – gvkv Apr 17 '11 at 09:02

7 Answers7

2

Unfortunately, this is not possible with CSS. However, in the special case where your elements are of equal width, this CSS hack makes it fairly easy.

With equidistant spacing between variable-width elements even specifying widths in percentages for each element's container will not suffice. This would still create a variable width between the elements.

This is probably possible to do with JavaScript on most modern browsers. Here is an example page demonstrating a poorly implemented JavaScript hack and proof that attempting to use text justification to solve this problem will not work reliably.

Trey Hunner
  • 10,975
  • 4
  • 55
  • 114
  • Thanks for responding to an old question. Unfortunately, elements are not of equal widths. At any rate, I ended up using JavaScript for my layout issues as necessary. – gvkv May 02 '09 at 06:36
2

If CSS3 is acceptable (ie, if how it looks in IE6 is not of primary importance), you can use the display property values of "table" and "table-cell" to use the table display model with any type of element; "inline-block" is also something to consider, which acts like a block without breaking a new line.

Anonymous
  • 49,213
  • 1
  • 25
  • 19
  • Thanks for responding on an old question. Actually, IE6 isn't the problem since I made an explicit decision to not support that browser but IE7 doesn't allow those tricks either and I will need to support that. I ended up using JavaScript. – gvkv May 02 '09 at 06:34
1

Best solution I've found is to center align the containing div then give each of the links a fixed and reasonable left and right padding that can accommodate both the long links and short ones. While this won't evenly space your links all the way across the top bar it will provide a visually pleasing effect.

<div style='text-align:center'>
    <a style='padding-left:10px;padding-right:10px'>Link 1</a>
    <a style='padding-left:10px;padding-right:10px'>Link 2</a>
    <a style='padding-left:10px;padding-right:10px'>Link 3</a>
</div>
Nick
  • 11
  • 1
1

Hmmm, sounds to me like you're creating a menu? You might want to use a list to hold your anchors and style the list accordingly. This is the commonly accepted best practice.

As for even distribution of elements, I was looking yesterday for something similar, I was hoping it would be in the CSS3 spec, but it's not (at least I can't find it) which seems like a major f*ckup if you ask me. Anyway...

Which leaves two options. CSS, and Javascript.

With CSS, use the margin-right property for each element. It's a good idea to create a .last class that sets margin-right to zero which prevents your last element from breaking the layout.

There's a bunch of javascripts out there that will do this for you. I prefer only to use JS when absolutely essential, so I couldn't comment on which one is best.

... there is one last thing you could try, but... you didn't hear this from me ok?

You could use a table. That is the quickest (and dirtiest) way to get what you want.

IMHO, and you probably don't want to hear this, but the design is probably flawed. It's common knowledge that distributing items evenly across a layout with CSS is a pain, so designers should avoid it.

UPDATE: You could also try

.link_container { text-align: center; }
.link_container a { margin-right: 10x; }
.last { margin-right: 0; }

then use something like this

<div class='link-container'>
    <a href='...'>Some line</a>
    <a href='...'>Some line</a>
    <a href='...'>Some line</a>
    <a class='last' href='...'>Some line</a>
</div>

That might get you close.

gargantuan
  • 8,888
  • 16
  • 67
  • 108
  • The margin-right property won't work since I don't know the size of the anchors. Tables are something I'm trying to avoid but I have been very tempted to use them multiple times throughout my design. – gvkv Mar 03 '09 at 15:29
  • 1
    Also, a design is not flawed because a standard is incomplete or broken. Distributing elements is a common activity in layout and there really is no excuse for CSS to not have a simple mechanism for implementing it. – gvkv Mar 03 '09 at 15:31
  • I hear you buddy. I've wasted many an hour screaming at my screen because of the failings of CSS. However, CSS is the standard, my designs are not. Overtime, I've come to know what can and can not be done and I design to CSS's strengths. CSS wont be changing anytime soon, so my designs must. – gargantuan Mar 03 '09 at 15:54
  • no, it's set to 0 so if if the "last" element reaches the far right of the parent elements container, the white space of the margin won't cause the element to wrap. – gargantuan Oct 06 '10 at 00:31
0

It's a bit unclear what you mean by "distributing evenly"; Could it be that you want to justify the contents of the paragraph?

p { text-align: justify; }
Brant Bobby
  • 14,956
  • 14
  • 78
  • 115
  • See edit on distributing evenly. Justifying doesn't work since the paragraph contents won't wrap and justification doesn't require the last line of a paragraph to be aligned on the right side. – gvkv Mar 02 '09 at 02:56
  • 1
    Using "text-align: justify" will work fine if a dummy, 0-height inline-block `
    ` is appended to the end of the content. It'll get its own line, forcing the actual stuff to be distributed. The font size of the container should be set to 0px to make this work.
    – Pointy Apr 15 '11 at 15:42
0

do your anchors have specific widths set? i think that might be necessary for any margin auto's to work.

0

using display: table on the container and display: table-cell on the items within seems to do the trick for me. It even works in IE8

<!DOCTYPE html>
<html>
<head>
<!-- insert reset CSS here -->
    <style type="text/css">
    #header {
        width: 940px;
        margin: 0 auto;
        background-color: #E6EFE6;
    }

    #main_nav {
        width: 100%;
        display: table;
    }

    #main_nav .nav-item {
        display: table-cell;
        text-align:center;
    }
    </style>
</head>
<body>
<div id="header">
    <ul class="" id="main_nav">
        <li class="nav-item first">
            <a href="#">Item 1</a>
        </li>
        <li class="nav-item">
            <a href="#">Item 2</a>
        </li>
        <li class="nav-item">
            <a href="#">Item 2</a>
        </li>
        <li class="nav-item">
            <a href="#">Item 2</a>
        </li>
        <li class="nav-item">
            <a href="#">Item 2</a>
        </li>
        <li class="nav-item">
            <a href="#">Item 2</a>
        </li>
        <li class="nav-item last">
            <a href="#">Item 3</a>
        </li>
    </ul>
</div>
<body>
</html>
PottyBert
  • 1,902
  • 1
  • 13
  • 14