Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The value for break-[before/after] is sometimes ignored #60

Open
RonaldTreur opened this issue Dec 7, 2020 · 0 comments
Open

The value for break-[before/after] is sometimes ignored #60

RonaldTreur opened this issue Dec 7, 2020 · 0 comments

Comments

@RonaldTreur
Copy link
Contributor

RonaldTreur commented Dec 7, 2020

What goes wrong

If there is an element with a CSS property break-before or break-after that also contains children, whose content ends up being split by the extractOverflowingContent-method, the algorithm will ignore the value set to this breaking-*-property.

The cause

The moment a single region can not contain all of the content (for whatever reason) extractOverflowingContent is being invoked. Once a suitable cut-off point has been detected, it will then traverse the content in the region bottom-up in order to detect any elements which have a break-before property set (or others, but that is irrelevant here).

It does so by executing the following code:

var current = r.endContainer; if(current.hasChildNodes()) { if(r.endOffset>0) { current=current.childNodes[r.endOffset-1] } };
var first = r.endContainer.firstChild;
do {
if(current.style) {
if(current != first) {
if(/(region|all|always)/i.test(cssCascade.getSpecifiedStyle(current,'break-before',undefined,true).toCSSString())) {
r.setStartBefore(current);
r.setEndBefore(current);
dontOptimize=true; // no algo involved in breaking, after all
}
}
if(current !== region) {
if(/(region|all|always)/i.test(cssCascade.getSpecifiedStyle(current,'break-after',undefined,true).toCSSString())) {
r.setStartAfter(current);
r.setEndAfter(current);
dontOptimize=true; // no algo involved in breaking, after all
}
}
}
} while(current = cssRegionsHelpers.getAllLevelPreviousSibling(current, region));

The backward traversal happens by invoking a helper-method cssRegionsHelpers.getAllLevelPreviousSibling on line 560:

} while(current = cssRegionsHelpers.getAllLevelPreviousSibling(current, region));

This method is pretty straightforward:

getAllLevelPreviousSibling: function(e, region) {
if(!e || e==region) return null;
// find the nearest ancestor that has a previous sibling
while(!e.previousSibling) {
// but bubble to the next avail ancestor
e = e.parentNode;
// dont get over the bar
if(!e || e==region) return null;
}
// return that sibling
return e.previousSibling;
},

It will return the previous sibling, unless it has none. In that case it moves up to its parent and returns its previous sibling. This however means the the actual parent-element is completely ignored. And this is why the problem described above occurs.

An example

Let's say we have content that looks like this:

...
<p>....</p>
<table>
...
<tr>..</tr>
<tr>..</tr>
...
</table>

and some styling that looks like this:

table { break-before: always }

If the table ends up overflowing a region, then a TR-element will end up being the target from which the algorithm will start looking for elements with a break-*-property set.

However, the getAllLevelPreviousSibling-method will skip over the table-element and move directly on to the paragraph preceding it. In effect, the table will not end up being moved to the subsequent region, it will be cut in two instead.

Possible fix

Taking the actual parent element also into account, instead of skipping it, should resolve this.

RonaldTreur added a commit to RonaldTreur/css-regions-polyfill that referenced this issue Dec 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant