Dealing with spacing in compiled markdown articles. This is one of those tasks that starts simple but gets complicated in the process: Applying vertical margins to elements inside an article, for example a blog post that consists of compiled markdown. web development Most of the time, you have to deal with exceptions and dependencies: Headlines and images need more whitespace. But if an image follows another image, there should be less whitespace between them. The whitespace between an and an should be larger than between an and a paragraph. And so on. h2 h3 h2 When I started with web development a couple of years ago, all those exceptions and dependencies always lead to convoluted code, visual inconsistencies and unexpected behavior. I definitely googled » « more than once. Why does margin-top not work What follows is a I’ve now been using for a while. It avoids collapsing margins, offers decent readability and allows for complex dependencies. technique Step 1 A simple article might look like this: <article class="article"> <h1>Hello World</h1> <p>Lorem ipsum dolor sit amet</p> <p>Lorem ipsum dolor sit amet</p> <img src="…" alt="…"> <p>Lorem ipsum dolor sit amet</p> <ul><li>Lorem</li><li>Ipsum</li><li>Dolor</li></ul> </article> I usually take two paragraphs and adjust the vertical margin between them so that it looks good. Then I use that value as the base margin for all elements. .article > * + * {margin-top: 1.5rem;} This rule adds to any direct children of that have an adjacent sibling. By only applying to direct children, I avoid any unwanted behavior. For instance: The in the HTML code above would receive , but not its . margin-top .article margin-top <ul> margin-top <li> In the CodePen below you can see an example: The margins that are applied by the CSS rule above can be highlighted. Step 2 In the next step I add more specific rules, for instance: .article > img + * {margin-top: 3rem;} Any element that follows an receives a specific . This is similar to applying to the directly. But using the adjacent sibling selector and has two advantages: I don’t have to remove from the and avoid collapsing margins. img margin-top margin-bottom img margin-top margin-bottom :last-child The CodePen below shows an extended example: The margins that are applied in this step can be highlighted. Step 3 In this step I add rules to specific elements, for instance: .article > * + h2 {margin-top: 4rem;} .article > * + img {margin-top: 3rem;} If an has an adjacent sibling, it receives a specific . The same goes for an image with an adjacent sibling. h2 margin-top Extended CodePen example: The margins that are applied in this step can be highlighted. Step 4 In the last step I deal with specific dependencies: .article > img + img {margin-top: 1rem;} If an image follows another image, the margin between them should be very small. Extended CodePen example: The margins that are applied in this step can be highlighted. And if you want, you can get even more specific. For instance: .article > img + img + img + h2 {margin-top: 5rem;} If an follow three images in a row, it receives a specific . Fortunately, this is an edge case. But it’s good to know that the adjacent sibling selector can solve such complex dependencies. h2 margin-top Advanced use To improve readability, I use ( ) nesting and write each rule in one line. I also don’t group selectors with the same value, since will take care of that in my build task. SCSS CSSO .article {> * + * { margin-top: 1.5rem } > h2 + \* { margin-top: 1rem } > img + \* { margin-top: 3rem } > \* + h2 { margin-top: 4rem } > \* + h3 { margin-top: 3.5rem } > \* + img { margin-top: 3rem } > img + img { margin-top: 1rem } > h2 + h3 { margin-top: 4.5rem } } This technique also work well with SASS or CSS variables, for example for baseline grids. If every margin is calculated from a base margin variable, you only have to change that variable to increase or decrease the overall whitespace. CodePen example using a CSS variable: Conclusion The websites we develop at our agency usually have very complex articles. They not only consist of compiled markdown, but also elements such as category titles, intro texts or nested layouts. Using the adjacent sibling selector and only allows me solve complex design requirements while maintaining comprehensible CSS rules. Especially if I have to add or adjust rules later on. margin-top
Share Your Thoughts