Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to position text on a baseline?

Tags:

html

css

PLAYGROUND HERE

HTML:

<div class="first">Hello g World</div>
<div class="second">Hello g World</div>

CSS:

div {
  background-color: rgba(255, 0, 0, 0.3); /* For visualization only */
  margin-top: 50px;                       /* For visualization only */
  height: 20px;                           /* This is fixed! */
}

.first {
  font-size: 16px;                        /* This can change */
}

.second {
  font-size: 30px;                        /* This can change */
}

Result:

enter image description here

How would you position the text such that its baseline (the bottom of "Hello") is aligned with the bottom of the pink box, i.e.:

enter image description here

Is there a way to achieve this regardless of the font-size?

PLAYGROUND HERE

like image 550
Misha Moroshko Avatar asked Oct 02 '14 12:10

Misha Moroshko


3 Answers

After searching ...and searching I came up with this very awesome tutorial at adobe's place about how to align text to baseline of an element.

USING PSEUDO-ELEMENT

I would suggest this one but take a look at all the story bellow (Road from .strut element to a single pseudo-element):

div {
  width: 400px;
  height: 100px;
}
.first {
  font-size: 24px;
  background-color: #9BBCE3;
}
.first::after {
  content: "";
  height: 100%;
  display: inline-block;
}
<div>
  <div class="first">Hello g World / With font-size: 24px</div>
</div>

USING AN EXTRA .STRUT ELEMENT

  • SCENARIOS AND RULES

Rule 1 (Larger Fonts): We want the height of the div to be fixed. For example 20px. So, the font-size must be equal or less to the .height value so as to work.In general,

~ THE FONT-SIZE MUST BE EQUAL OR LESS THAN THE FIXED HEIGHT.THEN IT WORKS FOR ALL SIZES WITH LESS VALUES

Scenario 1: Suppose that we have larger fonts than the 20px of this case.

See it in action: http://jsfiddle.net/csdtesting/pvw5xhku/

div.forall {
  width: 700px;
  height: 48px;
  border: thin black solid;
  background-color: #9BBCE3;
  margin-top: 20px;
}
.inText {
  font-size: 48px;
  line-height: 48px;
}
.inText3 {
  font-size: 22px;
  line-height: 22px;
}
.strut {
  height: 48px;
  display: inline-block;
}
<div class="forall">
  <div class="inText">Hello g World /With font-size 46px
    <div class="strut"></div>
  </div>
</div>
<div class="forall">
  <div class="inText2">Hello g World /With font-size 32px
    <div class="strut"></div>
  </div>
</div>
<div class="forall">
  <div class="inText3">Hello g World /With font-size 32px
    <div class="strut"></div>
  </div>
</div>
enter image description here
  • EXPLANATION

All the magic about this implementation is about the .strut element.This is the one with display:inline-block; property! I wondered ...what is that again ?!

The baseline of the strut is placed at its bottom margin edge, which is determined solely by the height of the strut in this case. And if the letter span’s line-height is smaller than the strut’s height, the letter’s baseline will move to match! Unbelievable!

  • MAIN IMPLEMENTATION

See it in action: http://jsfiddle.net/csdtesting/bm2yz3ec/

div.forall {
  width: 300px;
  height: 20px;
  border: thin black solid;
  background-color: #9BBCE3;
  margin: 10px;
}
.inText {
  font-size: 20px;
  line-height: 20px;
}
.intext2 {
  font-size: 9px;
  line-height: 9px;
}
.strut {
  height: 20px;
  display: inline-block;
}
<div class="forall">
  <div class="inText">Hello g World /With font-size 20px
    <div class="strut"></div>
  </div>
</div>
<div class="forall">
  <div>Hello g World / Without font-size
    <div class="strut"></div>
  </div>
</div>
<div class="forall">
  <div class="intext2">Hello g World / with font-size:9px
    <div class="strut"></div>
  </div>
</div>

enter image description here

like image 99
Giannis Grivas Avatar answered Nov 02 '22 00:11

Giannis Grivas


Yes, to some extent: you can manipulate the position of text using a combination of line-height and a choice of other properties, including setting margins and padding, or using position: relative and top. There are other techniques if you only have one line that needs positioning (e.g. if you're creating a drop cap); I will cover positioning techniques that work on one and multiple lines.

There is the rather large caveat to this that type rendering varies between OSes and browsers, and it is going to be difficult to control your text precisely, particularly if you want pixel-perfect control.

By default, browsers position text roughly in the middle of the line, as defined by the line height. There is not a defined baseline for text that is invariant between browsers, so positioning varies between browsers.

The idea when setting up vertical rhythm is to have all your text falling at certain intervals. To do this, you need to control font size (which most people do anyway), line height, and anything that will add vertical space to your design: borders, padding, and margin. You select your "rhythm unit"--in your case, 20px--and then set your text to align with it. Your line height should be equal to your rhythm unit (i.e. 20px); for large font sizes, use multiple of the rhythm unit (e.g. 40px, 60px) to ensure the text stays in rhythm. The combination of borders, padding, and margin should add up to your rhythm unit to keep everything in line.

I've made the following JS Fiddle to illustrate the next piece of code.

As mentioned earlier, text gets vertically centered(-ish) by the browser, so it doesn't sit nicely on a grid; the text baseline moves around when using different font sizes. Here are a couple of ways to deal with that.

Here's our sample HTML:

<article>
  <section>
    <h2>Title!</h2>
    <div class="first">Hello g World<br />Lorem ipsum...</div>
    <div class="second">Hello g World<br />Lorem ipsum...</div>
    <div class="first">Hello g World<br />Lorem ipsum...</div>
  </section>
</article>

We'll give it the following basic css:

article {
  margin: 0;
  padding: 0;
  line-height: 20px;  /* 20px is our "unit of rhythm" */
}

div {
  margin: 20px;
}

h2 {
   font-size: 24px;
   line-height: 40px;  /* double our rhythm unit */
}

.first {
   font-size: 16px;
}

.second {
  font-size: 30px;
  line-height: 40px;  /* double our rhythm unit */
}

Using position: relative and top:

Visually align text by positioning it relatively to the background grid.

Give the section element the class rel and add the following CSS:

.rel, .rel .first, .rel .second {
   position: relative;
}
.rel .first {
    top: 4px;
}
.rel .second {
    top: 9px;
}

JS Fiddle - half way down the page

This pushes the text down from its natural position. Unfortunately, this alignment has to be done by eye and yep, it does vary from browser to browser. Pages are usually internally consistent--i.e. text lines up with the grid, even if it is uniformly a couple of pixels higher in some browsers.

Using padding and/or margin

The sum of the top and bottom padding must equal our unit of rhythm. Again, alignment has to be done by eye and may differ between browsers.

.ptop .first {
    padding-top: 24px;
    padding-bottom: 16px;
    margin: 0 20px; /* get rid of the massive gap! */
}

.ptop .second {
    padding-top: 30px;
    padding-bottom: 10px;
    margin: 0 20px; /* get rid of the massive gap! */
}

JS Fiddle - scroll to the bottom

You can also use margins, but care must be taken with collapsing margins to ensure the rhythm stays intact.

That is a whistlestop guide to a couple of methods for establishing vertical rhythm. I've skimmed over the details, so I would advise you to read up about this online -- there is a great article about vertical rhythm at 24ways, and another good one at A List Apart. There are also some vertical rhythm generators to stop you doing too much pixel-fiddling yourself.

like image 33
i alarmed alien Avatar answered Nov 01 '22 22:11

i alarmed alien


try adding line-height attribute as well:

div {
  background-color: rgba(255, 0, 0, 0.3); /* For visualization only */
  margin-top: 50px;                       /* For visualization only */
  height: 20px;                           /* This is fixed! */
  line-height: 20px;
}

UPDATE

Setting height and line-height to the same value aligns text vertically by center:

JSBIN

If you only use 16px and 30px that might be enough for you. If you need this to work with all values, I would suggest you use another layout, something like this:

<div class="container">
  <span class="align-bottom">Hello g world</span>
</div>
like image 4
Jay Avatar answered Nov 01 '22 22:11

Jay