Love your :first-child

Integrating block elements with TYPO3 content elements and CSS frameworks the headache-free way.

In this article I want to point out a mistake or two that I’ve been guilty of myself, which tend to lead to a style maintenance nightmare further down the road.

In TYPO3 basic content consists of a paragraph of text with an optional header. This  integrates very nicely with Bootstrap or Foundation, but of course every solution and every customer is special, so there is always something to tweak:

“Please move the header flush to the top of the container”

No problem! Here is a simplified version of the original bootstrap css:

/* bootstrap */
h1 {
    margin-top: 20px;
    margin-bottom: 10px;
}

/* fix: make header flush with top of container */
h1 {
    margin-top: 0px;
}

This makes the header sit neatly at the very top of its container. Problem solved.

Until somebody decides the world is a real and nasty place and produces something unexpected:

<h1>Header 1</h1>
<p>Lorem Ipsum … </p>
<h1>Another Header</h1>
<p>Some more Lorem Ipsum… </p>

And we just set ourselves up for a new problem in disguise:

“Now the text is stuck to all headlines!”

Of course we have a fix for this, all we need to do is put some margin on top of the paragraphs:

/* fix: give paragraphs a little more margin to their headline */
p {
    margin-top: 10px;
}

Easy enough fix. And this is usually promptly followed up with a realization:

“Text doesn’t sit on top of the container”

You may say now that a paragraph at the beginning of content should always have a headline, sadly the world is – as mentioned before – a nasty place and if an editor doesn’t produce this edge case it will arise in one form or another somewhere else.

A better solution

What we really should have done to begin with is:

h1:first-child, p:first-child {
    margin-top: 0px;
}

This solution leaves one important attribute of most block-level elements as found in CSS frameworks intact:

They have a top and a bottom margin that is prevented from collapsing vertically.

This is important because it helps us stack content on top of each other, even when the sequence it appears in is somewhat unpredicted. For example, consider the following markup:

<h1>Header 1</h1>
<h2>Header 2</h2>
<p>Lorem Ipsum … </p>
<h1>Another Header</h1>
<p>Some more Lorem Ipsum… </p>

or this

<h1>Header 1</h1>
<h2>Header 2</h2>
<p>Lorem Ipsum … </p>
<h1>Another Header</h1>
<p>Some more Lorem Ipsum… </p>

or this

<p>Lorem Ipsum … </p>
<h1>Another Header</h1>
<p>Some more Lorem Ipsum… </p>
<h2>Header 2</h2>
<p>Lorem Ipsum … </p>
<p>Lorem Ipsum … </p>
<p>Lorem Ipsum … </p>
<h1>Another Header</h1>
<p>Some more Lorem Ipsum… </p>

Every top and bottom margin on every block element will add up to the desired total margin, no matter which order these block elements appear in.

What about IE8?

Bless you.

Seriously though, there are multiple ways of dealing with this. As this method degrades rather gracefully and IE8 is a dying breed I have not looked into any polyfills specifically for this but I’m sure there are several floating around and I know jQuery supports this selector down to IE6.

Caveat

Mix and match your block level elements!

Make sure that two block level elements add up to the combined margin you want, override it in special cases as needed, such as for the first element or in special containers.

Anfrage