Just about everyone is familiar with Fark or slashdot style icons which accompany stories. There are plenty of other examples and situations which give rise to a repetitive use of images. When confronted with this situation, a good web developer looks at the situation and thinks "a ha! a list."
In the case of outputting Fark style headlines, it is fairly simple:
This example does a couple things. First, the images are clickable. This is the effect of using the anchor to add the background image. This has some unfortunate consequences which we must handle. First, since anchors are inline, adding the left padding will only apply to the first line. This means that multiline titles will wrap underneath. So we must handle this case. The second should be sort of obvious if you change the font-size. The image is placed in the top left of the image, not centered on the first line. This may cause some headaches, but overall is a small price. Here's the CSS:
ul.fark, ul.fark li {
/* clear default behaviors */
list-style: none; margin: 0; padding: 0;
}
ul.fark li {
/* 57px is the width of the image, this shifts
everything in the block over 57px */
padding-left: 57px;
/* this makes the first line of the list item
actually start in the negative. It will be wiped
out by the padding-left on the anchor */
text-indent: -57px;
/* give some space between links */
margin-bottom: .5em;
}
ul.fark li a {
/* padding on an inline element is only
applied to the first line -
this works in conjunction with the text-indent
above
*/
padding-left: 57px;
/* this should be the default icon */
background: url(/amusing.gif) no-repeat top left;
}
/* every list-item is classed with its corresponding
category, from which the icon is specified,
if the class doesn't exist, it reverts to the default */
ul.fark li.photoshop a{
background-image: url(/photoshop.gif);
}
ul.fark li.silly a {
background-image: url(/silly.gif);
}
To fix the not centered on the line issue, you can always change the background-position property to something more appropriate.
The fark icons fit on a single line. What happens if you want a big image that appears "floated" to the left of your headline? Or, what happens if you have the "headline" and a date or a byline?
Both situations require extrapolating what we know. Let's first look at a really simple, albeit less functional, method. This is probably the prototypical way something like this is implemented.
This example uses multiple dl/dt/dd sets to create the icons. That background is applied simply to the dl, and the dd and dt are given a left margin equivalent to the width of the icon. It's simple.
/* clear default behaviors */
#first dl, #first dl dd, #first dl dt { margin: 0; padding: 0; }
/* set a default background-image */
#first dl {
background: url(/newsicons/esports.gif) no-repeat top left;
}
/* alter the background by category using a class */
#first dl.kg {
background-image: url(/newsicons/kg.gif);
}
/* the image is 50px, offset both dl/dd by
a margin-left of 50px */
#first dl dd, #first dl dt { margin-left: 50px; }
/* separate news stories alittle */
#first dl dd { margin-bottom: .5em; }
This is VERY close to what we want. However, it requires a bit more markup than I'd prefer. In particular, every news story becomes its own list. Not particularily semantic. Moreover, clicking the background image doesn't take you to the story.
Let's try another way.
The following list has clickable left images; magic, I know! Here, we incorporate some of what we learned from the Fark example. In particular, since we are applying the background to the image, we need the padding-left and text-indent "trick." This time, however, we have one other problem.
Since the image is taller than a single line of text, applying the background to an inline element will cut it off at the line-height. In this case, we'd see just about half the image at a normal font size. That's no good.
This time we can use the often overlooked fact that applying vertical padding to an inline element will stretch its "box" without altering the behavior or subsequent lines. We can see this behavior on this example: Hi, I have a very big bottom.
In that example, the green box stretches, but doesn't alter any subsequent text, including this one. So how do we make this work for us?
By applying bottom-padding, we can make the background-image appear, but still allow text to flow normally.
/* clear silly default properties */
#alternate dl, #alternate dl dd, #alternate dl dt { margin: 0; padding: 0; }
/* this is related to the fark trick above
50px is the width of the "icon",
the first line is the only line that applies
text-indent. Everything else will be offset 50px;
*/
#alternate dl dt {
padding-left: 50px;
text-indent: -50px;
}
#alternate dl dt a {
/* set a default image, and background properties */
background: url(/newsicons/esports.gif) no-repeat top left;
/* 37px is the height of the background image,
padding is applied to the bottom of the anchor
so as to make enough room for the image
50px is the width of the image. We need to start the first
line off 50px so as to not conflict with the image, see
the above */
padding: 0 0 37px 50px;
}
/* every "category" would get its own icon */
#alternate dl dt.kg a {
background-image: url(/newsicons/kg.gif);
}
/* The DD also needs to be offset from the image, but it
doesn't need the text-indent fix.
AND
separate each story with a bit of space space */
#alternate dl dd { margin: 0 0 1em 50px; }
That's all she wrote!