16

As you can see in the following Fiddle: http://jsfiddle.net/EvWc4/3/, I'm currently searching a way to align the second link (link-alt) to the right side of its parent (p).

Why not using float or position:absolute you'll say, well the main reason is that I like the fact that the links' display (inline-block) property allow them to be verticaly aligned in a naturally kind of way.

By using float or position:absolute; I'll be forced to calculate and put some extra margin-top or top value to vertically aligned the links.

Here is the code but better see the Fiddle http://jsfiddle.net/EvWc4/3/ :

    <p>
        <a href="#" class="link">link</a>
        <a href="#" class="link link-alt">link alt</a>
    </p>

    p {
       padding: 20px;
       background: #eee;
    }
    .link {
       display: inline-block;
       padding: 10px;
       background: #ddd;
    }
    .link-alt { padding: 20px; }
Cœur
  • 37,241
  • 25
  • 195
  • 267
inwpitrust
  • 561
  • 3
  • 7
  • 20

7 Answers7

9

CSS3 flex and grid items are supposed to address these issues, but standard support remains spotty as of 2013.

Back to the real world. I don't think it is possible to do this purely in CSS2.1 (IE8+) without pixel hacks. The thing is, text alignment is controlled by the parent element, and since the two anchors share their parent, they either both align to the left or to the right. And justify doesn't work on the last line.

If you can suffer a little additional HTML, there are two approaches:

1) Add another inline that is guaranteed to wrap the line, and then try to hide the empty line. This allows you to use text-align justify on the parent.

<p>
    <a href="#" class="link">link</a>
    <a href="#" class="link link-alt">link alt</a>
    <span class="boom"></span>
</p>

<style type="text/css">
    p {
        padding: 20px;
        background: #eee;
        text-align: justify
    }

    .link {
        display: inline-block;
        padding: 10px;
        background: #ddd;
    }

    .link-alt {
        padding: 20px;
    }

    span {
        display: inline-block;
        height: 0;
        width: 100%
    }
</style>

Pros: works on any number of inline blocks, not just two. Only a little extra HTML required.

Cons: takes extra effort to hide the last (empty) line of text (setting the inline block inside of it to 0 height won't help you), and you're going to have to fiddle with margins or something else to make it really work. Further discussion: How do I *really* justify a horizontal menu in HTML+CSS?

2) Add another layer of inline blocks on top of your anchor tags and size them to 50%. Then you can apply separate text-align to get the final layout you requested. It is important that no whitespace is allowed between two inline blocks sized to 50%, or you'll wrap the line.

<p>
    <span class="left">
        <a href="#" class="link">link</a>
    </span><span class="right">
        <a href="#" class="link link-alt">link alt</a>
    </span>
</p>

<style type="text/css">
    p {
        padding: 20px;
        background: #eee;
    }

    .link {
        display: inline-block;
        padding: 10px;
        background: #ddd;
    }

    .link-alt {
        padding: 20px;
    }

    span {
        display: inline-block;
        width: 50%
    }

    .left {
        text-align: left
    }

    .right {
        text-align: right
    }
</style>

Pros: produces the exact layout you requested without polluting the outer box model.

Cons: only works for two inline blocks (you can try to extend it, but it quickly gets really complicated). Relies on having no extra whitespace, which could jeopardize your nicely formatted markup.

Community
  • 1
  • 1
Daniel S.
  • 3,494
  • 24
  • 30
9

To do this with CSS3 you can use the flex box model

HTML:

<div class="content">
    <div class="box box1"><a>Link 1</a></div>
    <div class="box box2"></div>
    <div class="box box3"><a>Link 2</a></div>
</div>

CSS:

.content {
    display: box;
    box-orient: horizontal;
    box-pack: center;
    box-align: center;
}
.box2 {
    box-flex: 1;
}

(needs vendor prefixes)

http://jsfiddle.net/EvWc4/18/

Petah
  • 45,477
  • 28
  • 157
  • 213
  • Thanks :) I think the same result can also be achieved with the new CSS3 Grid Alignement module http://msdn.microsoft.com/library/hh673536.aspx#grid_alignment (ie10 only though) – inwpitrust Feb 08 '12 at 23:33
  • IE 10 should also support flex box though. – Petah Feb 08 '12 at 23:50
  • 6
    This answer was correct at the time but is now outdated, you should use the new flex-box spec https://developer.mozilla.org/en/docs/Web/CSS/flex – nickspiel Jul 23 '15 at 04:17
5

You could set the position to absolute and use right: 0

.wrapper {
    position: relative;
}
.right {
    position: absolute;
    right: 0;
}

http://jsfiddle.net/EvWc4/13/

Petah
  • 45,477
  • 28
  • 157
  • 213
  • Thanks for your response but with this solution how do I get the links vertically aligned ? (middle, top, baseline, ...) – inwpitrust Feb 08 '12 at 22:57
  • We are getting away of the main issue here. I'm trying to keep the links vertically aligned BETWEEN them (without regards of their respective height). thanks for your help – inwpitrust Feb 08 '12 at 23:19
  • @inwpitrust Well you wont find an elegant way to do this, and support IE. See my CSS3 answer. – Petah Feb 08 '12 at 23:25
4

I believe this accomplishes what you're looking for:

.link-alt {
    position: absolute;
    right: 0; top: 0; bottom: 0;
    margin: auto;
    max-height: 1em;
}

You can use position: absolute and right: 0 to obtain the right alignment. To keep the vertical centering, you can use top: 0; bottom: 0; margin: auto;. Of course, you'll also need to set a height on the element, or it will stretch to the full height of its parent.

Here's a jfiddle: http://jsfiddle.net/pHppA/

James Duffy
  • 1,387
  • 8
  • 16
2

I've updated Pethas example, so it can be done in pure CSS2. It doesn't work in IE7, as it doesn't support display: table-cell; which I use.

http://jsfiddle.net/EvWc4/133/

curly_brackets
  • 5,491
  • 15
  • 58
  • 102
1

The attribute float has no bearing on the element's vertical positioning.

p{padding:20px;background:#eee;overflow:auto;}
.link-alt{padding:20px; float:right}

should accomplish what you're looking for. Setting the overflow of the parent to something besides it's default (visible) will force it to treat floating children like normal elements.

Reference article

Will P.
  • 8,437
  • 3
  • 36
  • 45
  • 2
    It does not : http://jsfiddle.net/EvWc4/14/ With float I loose my beautiful default vertical-align:middle; – inwpitrust Feb 08 '12 at 22:49
  • set the parent element's overflow to something besides visible. Edited answer to reflect. – Will P. Feb 08 '12 at 23:03
  • 1
    I'm aware that floated elements are taken out of the flow. This is not part of the problem that I'm trying to solve. but thanks for your help. – inwpitrust Feb 08 '12 at 23:16
  • That's not the point. The point is that it accomplishes what you describe without any calculation http://jsfiddle.net/EvWc4/17/ – Will P. Feb 08 '12 at 23:19
  • 2
    Yep but how would you get the first link to be vertically aligned (middle) with the second ? – inwpitrust Feb 08 '12 at 23:23
0

I haven't tested this at all outside of Chrome, so it might suck for IE.

This simple (and limited) solution leverages text-align: right and width: 50% on the aligned children, and white-space: nowrap on the parent to achieve the desired result.

Example: http://jsfiddle.net/erikjung/ejcJZ/

.vertically-centered-module {
    white-space: nowrap;
}

.vertically-centered-module > * {
    display: inline-block;
    vertical-align: middle;
    width: 50%;
}

.vertically-centered-module > :last-child {
    text-align: right;
}