An article by ERT Mentor GrandSchtroumpf
To achieve exact alignment of a background image with the first line of text of a block element for the two most common alignments:
We can use a background-image on a block so that it acts as "icon" or "marker" ("marker" is the CSS term for the "bullet" in front of list items).
This technique can replace the "list-style-image" CSS property on lists. Image markers on lists are not very flexible and do not display consistently in different browsers.
The dimensions of images are expressed in "px" (relative to the canvas resolution) while the dimensions of lines of text are expressed in "em" (relative to the font-size). The trick to achieve exact alignment is to combine a padding expressed in "px" with a background-position expressed in "em".
In the examples hereunder we will use DIV element (since DIV is the generic block-element) with this 8px by 8px image as background:
.
In a real case, the element will probably be a LI or a H1-H6.
To better show the vertical alignment, we will specify an explicit width on the element so that the content wraps on at least two lines and we will give the element a background color and a border.
<div class="example"> Lorem ipsum dolor sit amet </div>
div.example {
width: 8em;
line-height: 1.2em;
margin: 1em 0;
color: black;
background-color: white;
background-image: url(marker.png);
background-repeat: no-repeat;
text-indent: 12px;
border: 1px solid #888;
}
The text-indent gives the effect that the marker is inside the text. To give the effect that the marker is outside the text, we can replace the text-indent with padding-left. In any case, that won't influence the alignment of the background image.
Using the common code, the middle of the line is .6em (half of the line-height) away from the top of the div and the middle of the image is 4px (half of the image height) away form the top of the div.
To align those points, we shift each point down by the distance that separates the other point from the top of the div. This means using a padding-top that is equal to half the height of the image and a vertical background-position that is equal to half the line height.
The distance between each alignment point and the top of the div is now equal to half the height of the image plus half the line-height. We can increase/reduce the text-size and the alignment will remain correct.
<div class="example example1"> Lorem ipsum dolor sit amet </div>
div.example1 {
padding-top: 4px; /* half the height of the background image */
background-position: 0 .6em; /* half the line-height */
}
Using the common code, the bottom of the image is 8px away from the top of the DIV. The distance between the top of the DIV and the baseline depends on the font and on the line-height (it is equal to the font ascent plus the half-leading). We can use the trial and error method to evaluate that distance for the current font and the current line-height (using "em" as unit of course). This page uses Verdana and a line-height of 1.2em. For these values, I estimated the baseline offset to be .99em. Remember to use web-safe fonts or the alignment might be slightly off on systems that do not support the font face you specified as first choice.
To align those points, we shift each point down by the distance that separates the other point from the top of the DIV. This means using a padding-top that is equal to the height of the image and a vertical background-position that is equal to the baseline offset.
The distance between each alignment point and the top of the DIV is now equal to the height of the image plus the baseline offset. We can increase/reduce the text-size and the alignment will remain correct.
<div class="example example2"> Lorem ipsum dolor sit amet </div>
div.example2 {
padding-top: 8px; /* height of the background image */
background-position: 0 .99em; /* line ascent (depends on the font face) */
}
In this example, we will use the centering the background image on the first line. Just to show that it's possible to do so, we will compensate the pixel-padding by using a corresponding negative top margin.
<ul class="listExample">
<li>Some list item</li>
<li>Another list item</li>
<li>Yet another list item</li>
</ul>
ul.listExample li {
list-style: none;
line-height: 1.2em;
margin: -4px 0 0 0;
padding: 4px 0 0 0;
background-position: 0 .6em;
background-image: url(marker.png);
background-repeat: no-repeat;
text-indent: 12px;
}
We can extend this technique to align any point of the background image with any point of the line of text. We just need to identify the "px"-offset of the point on the background image and the "em"-offset of the point on the line of text and apply those as top padding and vertical background position.
This technique is extremely simple, it's just a matter of correctly combining "px" units with "em" units. So, why would we settle for approximate alignment when we can have exact alignment that will gracefully support any text-size/font-size change?
This page is licensed under a Creative Commons Attribution 2.5 License
© Copyright GrandSchtroumpf 2006-2007