# css - select only when followed by specific element

I have a specific problem in which I need to remove the margin-bottom of every Element that has a class only when followed by the same element with the same class. So p.1 has a margin-bottom:1em to give space to any other element that comes after it. But if p.1 is followed by another p.1 the margin-bottom should be 0. The thing is, I can't just give p.text a margin-top because of reasons I don't really want to elaborate.

<p class="text">text</p>
<p class="1">___</p>
<p class="1">___</p>
<p class="1">___</p>
<p class="text">text</p>


So in this exhample the first and second p class="1" need to be selected. I tried p.1 + p.1 but this only selects the second and third because it selects the sibling preceded by another one and not the sibling that is followed by one. Is this understandable?

Is there any way to do that in EPUB2?

• Instead of saying epub2, why not tell us which reading system you are talking about. Generally no epub2 system supports adjacent selectors, but current epub readers support generally support some parts of epub3. – idiotprogrammer Jul 16 at 15:44
• but if it's not declared with the namespace for epub3 how could I use parts of epub3 in dese files? I need it for ADE based readers. As in Tolino... – SabineR Jul 18 at 7:55
• fyi, all epub-reading systems (AFAIK) can open and read epub3 files (Whether they support its features is another matter). So I would always create epub3 files instead of epub2 files -- unless there is a specific reason justifying the exception. – idiotprogrammer Jul 19 at 13:58

Here's the spec. http://www.idpf.org/epub/20/spec/OPS_2.0_latest.htm#Section3.1

Support for these css features were limited in EPUB2, plus it's also a question of whether the device or app will support this. Most reading systems have nominal support for EPUB3 (and that's really important for css support). For example, most reading systems today support css media-queries, which is an epub3 feature.

A key thing is to check whether the epub standard requires that the reading system supports this css property. If it's optional, there's a good chance it won't be supported.

I would ask which reading system you are talking about. The most likely reading system to support this feature would be Google Play books -- although even that's iffy. Mostly software reading systems have better support for these css advanced features. I am curious about whether Adobe Digital Editions supports adjacent selectors. (That's the key test). My guess is no.

The most recent Amazon Kindle Publishing Guidelines specifically says that it does not support using the plus sign (+) selector (also known as adjacent sibling selectors) in css code. Sometimes, however, it supports a feature unofficially until it has been tested fully.

Aside from the Amazon publishing guidelines, there's no good reference about css support except for the epub spec. Often I have to do trial and error to see whether a certain feature is supported.

• I need the ebup to be compatible with ADE. It's weird that the kindle guidelines say that they don't support the +-sign. I already use it and the kindle previewer never reported it (only cases of max-height for some reason). – SabineR Jul 18 at 8:21
• Sometimes Kindle supports things unofficially without it being in the guidelines. You can only learn about these undocumented features by trying things out yourself or hearing about it from someone else :) – idiotprogrammer Jul 19 at 13:55
• Also, my guess is that the e-ink devices do not support this CSS. (Maybe Kindle Previewer shows it working correctly, but if you tested it on an actual device, you may find something different). – idiotprogrammer Jul 19 at 13:59

As you've discovered, the challenges here are that:

1. in CSS, it's not possible to select a parent or ancestor element by its child; the browser applies CSS 'downwards' only; and
2. you can't know what CSS properties and selectors EPUB2-capable readers will actually support.

If I've understood your needs correctly, here are three possible options you could try. For readability I've renamed your 1 class as line.

Option 1

.line {
margin: 0;
}
.line + .text {
margin-top: 1em;
}


Option 2

.text + .line {
margin: 0;
}
.line + .line {
margin: 0;
}


Option 3

* + .line {
margin: 0;
}


I've created a pen here to demo these: https://codepen.io/arthurattwell/pen/NQKRrp Just comment out/uncomment the options in the CSS to see how they behave there. You'd need to test in some older EPUB2 readers to see what really works. As @idiotprogrammer explains, support for the adjacent sibling selector (+) is very unpredictable. As I see it, users whose readers support it get your ideal spacing, and those that don't can still read the content at least.

• Thank you. Sadly it doesn't work. Option 1 and 2 can't be used anyway, because the elements before and after are various and not only a specific p.text. And the 3. Option doesn't work because it still selects the p.line folowed by any other element and class. (Even though I'm not sure how it works with your exhample anyway) – SabineR Jul 18 at 8:17
• In general, I find that software-based reading systems support these advanced css features better than hardware-based. The main exception is css media queries (an epub3 feature) which was supported almost immediately in all reading systems... – idiotprogrammer Jul 19 at 13:53

Okay, I kind of found an answer (for this case at least) myself. The key was to walk away from the margin-bottom and look at it the other way around. So first deleting the margin-bottom from p.line and then putting a margin-top on any element that follows the p.line. And then putting the margin-top to "0" on all p.lines that are preceded by another p.line.

That still won't erase the margin from the first p.text but it at least keeps the same classes together and separates to the next different element/class

css

p {
margin-bottom:1em;
}
p.line {
margin-bottom: 0;
}
p.line + *{
margin-top:1.5em;
}
p.line + p.line {
margin-top: 0em;
}


html

<p class="text">text</p>
<p class="line">___</p>
<p class="line">___</p>
<p class="line">___</p>
<p class="text">text</p>

• Nice! Perhaps similarly to you, I always aim to handle vertical spacing with margin-bottom, to avoid getting unexpected results as I add to complex CSS files over time. But sometimes the occasional margin-top with a sibling selector is the only way to achieve a desired result. – Arthur Jul 20 at 8:38