What goes wrong
Having an element with a CSS property break-before set to region, always or all breaks the polyfill in most cases. What happens is that extractOverflowingContent will correctly detect the element that has this property, upon which it decides to make the cut right before it. However, it only does this if it is not the "first" element (in the region). However, the current check only picks out very specific use-cases, and misses most.
The end result is that all regions are empty, except the last, because the algorithm could not move the content further and put it all in there.
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)); |
Its attempt to not cause this issue can be found on line 543, where it is trying to make sure this is not the first item:
Determining the first item is done on line 539:
|
var first = r.endContainer.firstChild; |
However, this is not correct. The range's endContainer is (unless we are in a single region-spanning element) very likely not the element with which this region's content starts.
Possible fix
Interesting enough, a variation of this check is performed earlier in the code, in the layoutContentInNextRegionsWhenReady-method. Here the following code is used:
|
var first = region.firstElementChild; |
|
var last = region.lastElementChild; |
|
var current = first; |
|
while(current) { |
|
|
|
if(current != first) { |
|
if(/(region|all|always)/i.test(cssCascade.getSpecifiedStyle(current,'break-before',undefined,true).toCSSString())) { |
|
shouldSegmentContent = true; break; |
|
} |
|
} |
This value for the first element (seen on line 130) is indeed the first element of the region and should most likely also be used by the extractOverflowingContent-method.
What goes wrong
Having an element with a CSS property
break-beforeset toregion,alwaysorallbreaks the polyfill in most cases. What happens is thatextractOverflowingContentwill correctly detect the element that has this property, upon which it decides to make the cut right before it. However, it only does this if it is not the "first" element (in the region). However, the current check only picks out very specific use-cases, and misses most.The end result is that all regions are empty, except the last, because the algorithm could not move the content further and put it all in there.
The cause
The moment a single region can not contain all of the content (for whatever reason)
extractOverflowingContentis 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 abreak-beforeproperty set (or others, but that is irrelevant here).It does so by executing the following code:
css-regions-polyfill/src/css-regions/polyfill.js
Lines 538 to 560 in d40c91b
Its attempt to not cause this issue can be found on line 543, where it is trying to make sure this is not the first item:
css-regions-polyfill/src/css-regions/polyfill.js
Line 543 in d40c91b
Determining the first item is done on line 539:
css-regions-polyfill/src/css-regions/polyfill.js
Line 539 in d40c91b
However, this is not correct. The range's endContainer is (unless we are in a single region-spanning element) very likely not the element with which this region's content starts.
Possible fix
Interesting enough, a variation of this check is performed earlier in the code, in the
layoutContentInNextRegionsWhenReady-method. Here the following code is used:css-regions-polyfill/src/css-regions/polyfill.js
Lines 130 to 139 in d40c91b
This value for the first element (seen on line 130) is indeed the first element of the region and should most likely also be used by the
extractOverflowingContent-method.