W3C home > Mailing lists > Public > www-style@w3.org > April 2016

Re: [css3-break] fragment selectors

From: Florian Rivoal <florian@rivoal.net>
Date: Wed, 20 Apr 2016 10:35:37 +0900
Cc: CSS WG <www-style@w3.org>, Lea Verou <lea@verou.me>
Message-Id: <BEDCA100-6DE8-4555-8533-1C5328EA27D6@rivoal.net>
To: Matt Haggard <haggardii@gmail.com>

On Apr 20, 2016, at 04:07, Lea Verou <lea@verou.me> wrote:
>> This is inherent to the way pseudo classes work, so we cannot have a pseudo class which matches or not depending on the result of layout.
> 
> Yes we can, and we do: ::first-line.
> I can almost imagine the CSS WG discussion about cycles if ::first-line was proposed now, yet it's implemented everywhere and works just fine.

First, as Tab pointed out, while we have ::first-line, it is a mess of difficult interop issues that we have yet to sort out. I am confident we eventually will, but we're not there yet and it is far from an easy one.

But even then, there's a big difference between ::first-line and ::nth-fragment on the one hand, and ::breaks-onto-the-next page on the other.

::first-line and ::nth-fragment(1) always match, even if there's no second line / second fragment. Depending on how you style them, content may shift between the first and the second fragment, but the first fragment will not stop existing or stop matching. It may be display:none, but even that won't prevent ::nth-fragment(1) from matching. As for the second fragment, it may not exist at all if all the content fits in the first fragment and there's no break. But if there is enough content to have a break and the second fragment does exist, nothing you can do with a ::nth-fragment(2) selector can stop the second fragment from existing. They may be hard to figure out, but these pseudo classes are possible (and I too hope we will get them eventually).

The same isn't true of ::breaks-onto-the-next page. The styles applied by a selector that uses it could change whether the break occurs, and therefore change if ::breaks-onto-the-next page applies. This which would cause infinite loops in the layout system, and that's what making it non-sensical / impossible, rather than merely hard.

Can we solve the use case with ::nth-fragment then? Actually I don't think so, because to do so, we'd need to select the first and the last fragments, to style the first top border and the last bottom border differently from the other borders. Selecting the first fragment is doable, but selecting the last one isn't, for a variant of the same reason as above: the properties applied by a ::last-fragment (or ::nth-last-fragment) cannot change whether there is a last fragment, but they can change which fragment is the last, which is just as bad. Just try to think of what font-size:50em or border-top-width:80vh or width:5px etc would mean if applied through such a pseudo element. You've just hit an infinite loop again.

On Apr 20, 2016, at 02:11, Matt Haggard <haggardii@gmail.com> wrote:
> What if, instead of `:orphan` and `:widow` targeting the broken element, they target new pseudo-elements (like `:before` and `:after`) that exist before and after page breaks?

That might actually work. I don't think there would be a way for a ::before-break pseudo element to prevent the break for happening, and therefore causing itself to stop existing. Same with an ::after-break.

Well, maybe we need to prevent these pseudos elements (or at least the one that comes before a break) from having negative top and bottom margins, as that could cause issues. But this kind of restrictions (such and such property does not apply to a certain element/pseudo element, or such and such value computes to such and such) are doable. Such restrictions may be annoying, but they're not at odds with the underlying model.

I need to think longer whether it's a good idea, but at least it seems to be a doable idea :)

On Apr 20, 2016, at 02:11, Matt Haggard <haggardii@gmail.com> wrote:
> 
> And Florian -- thank you for taking the time to write out a workaround.  I could see if getting a little crazy to cover the top/bottom with white since my actual use case has rounded corners on the top/bottom AND sometimes has a caption box, etc... etc...

+

On Apr 20, 2016, at 04:07, Lea Verou <lea@verou.me> wrote:
> What you're proposing is a terrible hack which only works in cases where one can just cover up the decoration with pseudo-elements (as pointed out in the replies, this is not always easy). This is issue is very common (in print, in CSS it's not common because people can't do it) to only be solvable with a terrible hack. As you're aware, I run into it in my book too, and had to solve it with a similar terrible hack.

Alright. I think of it as a clever hack rather than a terrible one, but I'll agree it's a hack, and that in fragmented media it is a decently common use case, so we may want to solve it in a non hacky way.

A (set of) properties that could let you change the appearance (but not the size, otherwise we're looping again) of the border-before-a-break and of the border-after-a-break might just work.

div {
  border: solid 1px;
  border-radius: 10px;
  box-decoration-break: clone; /*we'll overriding the style around the break, but we need the border to exist and take space */

  border-before-break-style: dashed;
  border-before-break-left-radius: 0;
  border-before-break-right-radius: 0;

  border-after-break-style: dashed;
  border-after-break-left-radius: 0;
  border-after-break-right-radius: 0;
}

The first fragment would look like

div {
  border: solid 1px;
  border-radius: 10px;

  border-bottom-style: dashed;
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

the last one like

div {
  border: solid 1px;
  border-radius: 10px;

  border-top-style: dashed;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

and any in-the-middle fragment would look like

div {
  border: solid 1px;
  border-radius: 0;
  border-top-style: dashed;
  border-bottom-style: dashed;
}

If you want to go with border images, maybe something like this:

div {
  border: 20px solid;
  border-image: url("my-normal-border.png") 20 20 repeat;
  box-decoration-break: clone;

  border-next-to-break-image: url("scissors.png") 20 20 repeat;
}

 - Florian
Received on Wednesday, 20 April 2016 01:36:05 UTC

This archive was generated by hypermail 2.4.0 : Friday, 25 March 2022 10:09:02 UTC