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

layout: Ensure empty list items are at least as tall as outside markers #32152

Merged
merged 1 commit into from
Apr 29, 2024

Conversation

mrobinson
Copy link
Member

While https://drafts.csswg.org/css-lists/#list-style-position-property says:

The size or contents of the marker box may affect the height of the
principal block box and/or the height of its first line box, and in some
cases may cause the creation of a new line box; this interaction is also
not defined.

All other browsers ensure that the first line of list item content is
the same block size as the marker. Doing this is complicated, but we can
ensure that the entire list item is at least as tall as the marker. This
should handle the majority of cases and we can make refinements later
for stranger situations, such as when the marker is very tall.

Co-authored-by: Oriol Brufau obrufau@igalia.com


  • ./mach build -d does not report any errors
  • ./mach test-tidy does not report any errors
  • There are tests for these changes

@Loirooriol Loirooriol added the T-linux-wpt-2020 Do a try run of the WPT label Apr 26, 2024
@github-actions github-actions bot removed the T-linux-wpt-2020 Do a try run of the WPT label Apr 26, 2024
Copy link

🔨 Triggering try run (#8853657889) for Linux WPT

Copy link

Test results for linux-wpt-layout-2020 from try job (#8853657889):

Flaky unexpected result (13)
  • FAIL [expected PASS] /_mozilla/css/iframe/hide_and_show.html (#15265)
  • OK /css/css-fonts/variations/at-font-face-font-matching.html (#20684)
    • PASS [expected FAIL] subtest: Matching font-weight: '400' should prefer '501 550' over '502 560'
    • PASS [expected FAIL] subtest: Matching font-weight: '399' should prefer '450 460' over '500 501'
    • PASS [expected FAIL] subtest: Matching font-weight: '399' should prefer '500 501' over '502 510'
    • PASS [expected FAIL] subtest: Matching font-style: 'italic' should prefer 'normal' over 'oblique 0deg'
    • PASS [expected FAIL] subtest: Matching font-style: 'oblique 21deg' should prefer 'oblique 10deg' over 'italic'
    • PASS [expected FAIL] subtest: Matching font-style: 'oblique -10deg' should prefer 'oblique -5deg' over 'oblique -1deg 0deg'
    • PASS [expected FAIL] subtest: Matching font-style: 'oblique -10deg' should prefer 'oblique -1deg 0deg' over 'oblique -20deg -15deg'
    • PASS [expected FAIL] subtest: Matching font-style: 'oblique -10deg' should prefer 'oblique -60deg -30deg' over 'oblique -50deg -40deg'
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/iframe-src-aboutblank-navigate-immediately.html (#29048)
    • PASS [expected FAIL] subtest: Navigating to a different document with form submission
  • OK /html/browsers/history/the-history-interface/traverse_the_history_4.html (#21383)
    • FAIL [expected PASS] subtest: Multiple history traversals, last would be aborted

      assert_array_equals: Pages opened during history navigation expected property 1 to be 5 but got 3 (expected array [6, 5] got [6, 3])
      

  • OK /html/browsers/history/the-history-interface/traverse_the_history_5.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/autofocus-dialog.html (#29087)
    • TIMEOUT [expected FAIL] subtest: <dialog>-contained autofocus element gets focused when the dialog is shown

      Test timed out
      

  • OK [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-2.html (#22154)
    • FAIL [expected NOTRUN] subtest: Check that popups from a sandboxed iframe do not escape the sandbox

      assert_equals: It came from a sandboxed iframe expected "null" but got "http://web-platform.test:8000"
      

  • OK /html/syntax/parsing/DOMContentLoaded-defer.html (#21550)
    • PASS [expected FAIL] subtest: The end: DOMContentLoaded and defer scripts
  • OK /html/webappapis/dynamic-markup-insertion/document-write/module-delayed.html (#27659)
    • FAIL [expected PASS] subtest: async document.write in a module

      assert_true: onload must be called expected true got false
      

  • TIMEOUT [expected OK] /resource-timing/nested-context-navigations-iframe.html (#24311)
    • TIMEOUT [expected PASS] subtest: Test that cross-site iframe navigations are not observable by the parent, even after history navigations by the parent

      Test timed out
      

    • NOTRUN [expected PASS] subtest: Test that iframe navigations are not observable by the parent
    • NOTRUN [expected PASS] subtest: Test that crossorigin iframe navigations are not observable by the parent
    • NOTRUN [expected PASS] subtest: Test that cross-site iframe navigations are not observable by the parent
    • NOTRUN [expected PASS] subtest: Test that iframe refreshes are not observable by the parent
    • NOTRUN [expected PASS] subtest: Test that crossorigin iframe refreshes are not observable by the parent
    • NOTRUN [expected PASS] subtest: Test that cross-site iframe refreshes are not observable by the parent
  • TIMEOUT [expected OK] /webmessaging/with-ports/017.html (#24486)
    • TIMEOUT [expected PASS] subtest: origin of the script that invoked the method, about:blank

      Test timed out
      

  • OK /workers/WorkerGlobalScope-close.html (#23064)
    • PASS [expected FAIL] subtest: Test sending a message after closing.
  • OK [expected ERROR] /workers/constructors/Worker/Worker-constructor.html (#22991)
Stable unexpected results that are known to be intermittent (16)
  • FAIL [expected PASS] /_mozilla/css/dirty_viewport.html (#13731)
  • FAIL [expected PASS] /css/css-sizing/dynamic-available-size-iframe.html (#31559)
  • OK /css/cssom-view/MediaQueryList-addListener-removeListener.html (#24569)
    • PASS [expected FAIL] subtest: listeners are called correct number of times
  • TIMEOUT [expected OK] /html/browsers/browsing-the-web/navigating-across-documents/javascript-url-referrer.window.html (#29081)
    • TIMEOUT [expected PASS] subtest: no-referrer referrer policy used to create the starting page

      Test timed out
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-cross-origin.sub.window.html (#29056)
    • FAIL [expected PASS] subtest: Cross-origin navigation started from unload handler must be ignored

      promise_test: Unhandled rejection with value: object "SecurityError: The operation is insecure."
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin.window.html (#29049)
    • PASS [expected FAIL] subtest: Same-origin navigation started from unload handler must be ignored
  • OK /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/a-click.html (#28697)
    • FAIL [expected PASS] subtest: aElement.click() before the load event must NOT replace

      assert_equals: expected "http://web-platform.test:8000/common/blank.html?thereplacement" but got "http://web-platform.test:8000/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20a%20%3D%20document.createElement(%22a%22)%3B%0A%20%20%20%20a.href%20%3D%20%22%2Fcommon%2Fblank.html%3Fthereplacement%22%3B%0A%20%20%20%20document.currentScript.before(a)%3B%0A%20%20%20%20a.click()%3B%0A%20%20"
      

  • TIMEOUT [expected OK] /html/browsers/history/the-history-interface/traverse_the_history_write_onload_1.html (#21581)
    • TIMEOUT [expected PASS] subtest: Traverse the history when a history entry is written in the load event

      Test timed out
      

  • OK [expected TIMEOUT] /html/infrastructure/urls/base-url/document-base-url-window-initiator-is-not-opener.https.window.html (#30970)
  • OK [expected TIMEOUT] /html/semantics/embedded-content/media-elements/track/track-element/no-cuechange-before-play.html (#31014)
    • FAIL [expected TIMEOUT] subtest: Ensure that the 'cuechange' event is not fired before video playback has begun.

      assert_true: Not expecting event, but got canplaythrough event expected true got false
      

  • CRASH [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html (#24066)
  • OK /html/semantics/embedded-content/the-img-element/sizes/parse-a-sizes-attribute-width-1000px.html (#21666)
    • FAIL [expected PASS] subtest: <img srcset="/images/green-1x1.png?e38 50w, /images/green-16x16.png?e38 51w" sizes="(min-width:calc(0)) 1px"> ref sizes="1px" (width:1000px)

      assert_equals: expected "http://web-platform.test:8000/images/green-1x1.png" but got "http://web-platform.test:8000/images/green-16x16.png"
      

  • OK [expected TIMEOUT] /html/semantics/forms/form-submission-0/reparent-form-during-planned-navigation-task.html (#29724)
    • PASS [expected TIMEOUT] subtest: reparent-form-during-planned-navigation-task
  • OK /html/semantics/forms/form-submission-0/urlencoded2.window.html (#28687)
    • FAIL [expected PASS] subtest: application/x-www-form-urlencoded: 0x00 in name (normal form)

      assert_equals: expected "a%00b=c" but got ""
      

  • OK [expected TIMEOUT] /webmessaging/with-ports/018.html (#24485)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, javascript:
  • OK [expected TIMEOUT] /webmessaging/without-ports/017.html (#24486)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, about:blank
Stable unexpected results (5)
  • FAIL [expected PASS] /css/CSS2/floats/floats-wrap-bfc-with-margin-010.html
  • OK /css/css-align/blocks/align-content-block-002.html
    • FAIL [expected PASS] subtest: .test 1: start

      assert_equals: 
      <div class="test" style="align-content: start" title="start">
          <div class="in-flow" data-offset-y="15"></div>
          <div class="in-flow">
            <span class="label">START</span>
            <span class="abspos" data-offset-y="0">ABS</span>
            <span class="relpos" data-offset-y="0">REL</span>
            <div class="overflow">OVERFLOW</div>
          </div>
        </div>
      offsetTop expected 15 but got 10
      

    • FAIL [expected PASS] subtest: .test 4: baseline

      assert_equals: 
      <div class="test" style="align-content: baseline" title="baseline">
          <div class="in-flow" data-offset-y="15"></div>
          <div class="in-flow">
            <span class="label">BASELINE</span>
            <span class="abspos" data-offset-y="0">ABS</span>
            <span class="relpos" data-offset-y="0">REL</span>
            <div class="overflow">OVERFLOW</div>
          </div>
        </div>
      offsetTop expected 15 but got 10
      

    • FAIL [expected PASS] subtest: .test 6: flex-start

      assert_equals: 
      <div class="test" style="align-content: flex-start" title="flex-start">
          <div class="in-flow" data-offset-y="15"></div>
          <div class="in-flow">
            <span class="label">FLEX-START</span>
            <span class="abspos" data-offset-y="0">ABS</span>
            <span class="relpos" data-offset-y="0">REL</span>
            <div class="overflow">OVERFLOW</div>
          </div>
        </div>
      offsetTop expected 15 but got 10
      

    • FAIL [expected PASS] subtest: .test 8: unsafe start

      assert_equals: 
      <div class="test" style="align-content: unsafe start" title="unsafe start">
          <div class="in-flow" data-offset-y="15"></div>
          <div class="in-flow">
            <span class="label">UNSAFE START</span>
            <span class="abspos" data-offset-y="0">ABS</span>
            <span class="relpos" data-offset-y="0">REL</span>
            <div class="overflow">OVERFLOW</div>
          </div>
        </div>
      offsetTop expected 15 but got 10
      

    • FAIL [expected PASS] subtest: .test 11: safe start

      assert_equals: 
      <div class="test" style="align-content: safe start" title="safe start">
          <div class="in-flow" data-offset-y="15"></div>
          <div class="in-flow">
            <span class="label">SAFE START</span>
            <span class="abspos" data-offset-y="0">ABS</span>
            <span class="relpos" data-offset-y="0">REL</span>
            <div class="overflow">OVERFLOW</div>
          </div>
        </div>
      offsetTop expected 15 but got 10
      

    • FAIL [expected PASS] subtest: .test 15: space-between

      assert_equals: 
      <div class="test" style="align-content: space-between" title="space-between">
          <div class="in-flow" data-offset-y="15"></div>
          <div class="in-flow">
            <span class="label">SPACE-BETWEEN</span>
            <span class="abspos" data-offset-y="0">ABS</span>
            <span class="relpos" data-offset-y="0">REL</span>
            <div class="overflow">OVERFLOW</div>
          </div>
        </div>
      offsetTop expected 15 but got 10
      

    • PASS [expected FAIL] subtest: .test 17: normal
  • OK /css/css-lists/list-and-margin-collapse-001.html
    • PASS [expected FAIL] subtest: list and margin collapse
  • PASS [expected FAIL] /css/css-lists/list-marker-alignment.html
  • OK /html/rendering/widgets/button-layout/display-other.html
    • FAIL [expected PASS] subtest: display: list-item

      assert_equals: buttonHeight expected 11 but got 24
      

Copy link

⚠️ Try run (#8853657889) failed.

Copy link
Contributor

@Loirooriol Loirooriol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somehow this breaks /css/CSS2/floats/floats-wrap-bfc-with-margin-010.html, even if it doesn't have list items...

@@ -257,20 +260,26 @@ impl OutsideMarker {
},
);

// Position the marker beyond the inline start of the border box list item. This needs to
// take into account the border of the item.
let pbm_of_list_item = self.list_item_style.padding_border_margin(containing_block);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But containing_block is the one of the marker, and this should get the one of the list item, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is the containing block passed in when laying out the children of the list item. We don't have access to the writing mode of the list item's parent here -- though this will be affected also by an implementation of marker-side. I've modified this to only call border_width() making it explicit that only the writing mode is important here.

What do you recommend?

components/layout_2020/flow/mod.rs Show resolved Hide resolved
Comment on lines 1792 to 1795
let mut collapsed_through = self.next_in_flow_margin_collapses_with_parent_start_margin;
if self.marker_block_size.is_some() {
collapsed_through = false;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't need to be mutable with

Suggested change
let mut collapsed_through = self.next_in_flow_margin_collapses_with_parent_start_margin;
if self.marker_block_size.is_some() {
collapsed_through = false;
}
let collapsed_through = match self.marker_block_size {
Some(_) => false,
None => self.next_in_flow_margin_collapses_with_parent_start_margin,
};

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've made this change.

@mrobinson
Copy link
Member Author

Somehow this breaks /css/CSS2/floats/floats-wrap-bfc-with-margin-010.html, even if it doesn't have list items...

It turns out that the offset from PlacementState can be negative! I guess this is due to negative clearance from floats. I've fixed this and left a comment.

@mrobinson mrobinson added the T-linux-wpt-2020 Do a try run of the WPT label Apr 27, 2024
@github-actions github-actions bot removed the T-linux-wpt-2020 Do a try run of the WPT label Apr 27, 2024
Copy link

🔨 Triggering try run (#8858507380) for Linux WPT

Copy link

⚠️ Try run (#8858507380) failed.

@mrobinson mrobinson added the T-linux-wpt-2020 Do a try run of the WPT label Apr 27, 2024
@github-actions github-actions bot removed the T-linux-wpt-2020 Do a try run of the WPT label Apr 27, 2024
Copy link

🔨 Triggering try run (#8859043012) for Linux WPT

Copy link

Test results for linux-wpt-layout-2020 from try job (#8859043012):

Flaky unexpected result (20)
  • FAIL [expected PASS] /_mozilla/css/dirty_viewport.html (#13731)
  • FAIL [expected PASS] /_mozilla/css/iframe/hide_and_show.html (#15265)
  • CRASH [expected OK] /_mozilla/mozilla/window_resizeTo.html
  • OK /css/css-fonts/variations/at-font-face-font-matching.html (#20684)
    • PASS [expected FAIL] subtest: Matching font-stretch: '100%' should prefer '100%' over '110% 120%'
  • OK /css/cssom-view/MediaQueryList-addListener-removeListener.html (#24569)
    • PASS [expected FAIL] subtest: listeners are called correct number of times
  • OK /custom-elements/form-associated/ElementInternals-setFormValue.html (#29174)
    • PASS [expected FAIL] subtest: Newline normalization - \r\n in value (urlencoded)
  • OK /html/browsers/browsing-the-web/navigating-across-documents/initial-empty-document/load-pageshow-events-window-open.html (#28691)
    • PASS [expected FAIL] subtest: load event does not fire on window.open('about:blank')
  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin.window.html (#29049)
    • PASS [expected FAIL] subtest: Same-origin navigation started from unload handler must be ignored
  • OK /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/a-click.html (#28697)
    • FAIL [expected PASS] subtest: aElement.click() before the load event must NOT replace

      assert_equals: expected "http://web-platform.test:8000/common/blank.html?thereplacement" but got "http://web-platform.test:8000/html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/resources/code-injector.html?pipe=sub(none)&code=%0A%20%20%20%20const%20a%20%3D%20document.createElement(%22a%22)%3B%0A%20%20%20%20a.href%20%3D%20%22%2Fcommon%2Fblank.html%3Fthereplacement%22%3B%0A%20%20%20%20document.currentScript.before(a)%3B%0A%20%20%20%20a.click()%3B%0A%20%20"
      

  • OK /html/browsers/browsing-the-web/overlapping-navigations-and-traversals/cross-document-nav-cross-document-nav.html (#29181)
    • PASS [expected FAIL] subtest: cross-document navigation then cross-document navigation
  • OK /html/browsers/history/the-history-interface/traverse_the_history_3.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • OK /html/browsers/history/the-history-interface/traverse_the_history_5.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • CRASH [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-1.html (#22647)
  • CRASH [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-3.html (#24066)
  • OK /html/semantics/forms/form-submission-0/multipart-formdata.window.html (#28725)
    • PASS [expected FAIL] subtest: multipart/form-data: Basic test (formdata event)
  • OK [expected TIMEOUT] /html/semantics/forms/form-submission-0/reparent-form-during-planned-navigation-task.html (#29724)
    • PASS [expected TIMEOUT] subtest: reparent-form-during-planned-navigation-task
  • ERROR [expected OK] /html/semantics/scripting-1/the-script-element/defer-script/async-script.html?reload (#29054)
  • TIMEOUT /html/webappapis/scripting/events/compile-event-handler-settings-objects.html (#24246)
    • PASS [expected FAIL] subtest: The entry settings object while executing the compiled callback via Web IDL's invoke must be that of the node document
  • TIMEOUT [expected OK] /html/webappapis/scripting/processing-model-2/integration-with-the-javascript-job-queue/promise-job-entry-different-function-realm.html (#25805)
    • TIMEOUT [expected FAIL] subtest: Fulfillment handler on pending-then-fulfilled promise

      Test timed out
      

    • TIMEOUT [expected FAIL] subtest: Rejection handler on pending-then-rejected promise

      Test timed out
      

  • TIMEOUT [expected OK] /webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.tentative.html (#29053)
    • TIMEOUT [expected PASS] subtest: StorageKey: test 3P about:blank window opened from a 3P iframe

      Test timed out
      

Stable unexpected results that are known to be intermittent (13)
  • FAIL [expected PASS] /_mozilla/mozilla/iframe/resize_after_load.html (#13573)
  • TIMEOUT /fetch/metadata/generated/element-img-environment-change.sub.html (#30111)
    • PASS [expected FAIL] subtest: sec-fetch-site - Not sent to non-trustworthy same-origin destination, no attributes
  • TIMEOUT [expected OK] /html/browsers/browsing-the-web/navigating-across-documents/javascript-url-referrer.window.html (#29081)
    • TIMEOUT [expected PASS] subtest: no-referrer referrer policy used to create the starting page

      Test timed out
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-cross-origin.sub.window.html (#29056)
    • FAIL [expected PASS] subtest: Cross-origin navigation started from unload handler must be ignored

      promise_test: Unhandled rejection with value: object "SecurityError: The operation is insecure."
      

  • OK [expected TIMEOUT] /html/semantics/embedded-content/media-elements/track/track-element/no-cuechange-before-play.html (#31014)
    • FAIL [expected TIMEOUT] subtest: Ensure that the 'cuechange' event is not fired before video playback has begun.

      assert_true: Not expecting event, but got canplaythrough event expected true got false
      

  • TIMEOUT [expected CRASH] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_escaping-2.html (#22667)
  • TIMEOUT [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-1.html (#24066)
    • NOTRUN [expected FAIL] subtest: Check that popups from a sandboxed iframe do not escape the sandbox
  • CRASH [expected TIMEOUT] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_popups_nonescaping-2.html (#22154)
  • OK /html/semantics/embedded-content/the-img-element/sizes/parse-a-sizes-attribute-width-1000px.html (#21666)
    • FAIL [expected PASS] subtest: <img srcset="/images/green-1x1.png?e38 50w, /images/green-16x16.png?e38 51w" sizes="(min-width:calc(0)) 1px"> ref sizes="1px" (width:1000px)

      assert_equals: expected "http://web-platform.test:8000/images/green-1x1.png" but got "http://web-platform.test:8000/images/green-16x16.png"
      

  • OK /html/semantics/forms/form-submission-0/urlencoded2.window.html (#28687)
    • FAIL [expected PASS] subtest: application/x-www-form-urlencoded: 0x00 in name (normal form)

      assert_equals: expected "a%00b=c" but got ""
      

  • OK [expected TIMEOUT] /webmessaging/with-ports/018.html (#24485)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, javascript:
  • OK [expected TIMEOUT] /webmessaging/without-ports/017.html (#24486)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, about:blank
  • OK [expected TIMEOUT] /webmessaging/without-ports/018.html (#24485)
    • PASS [expected TIMEOUT] subtest: origin of the script that invoked the method, javascript:

Copy link

✨ Try run (#8859043012) succeeded.

@@ -257,20 +260,28 @@ impl OutsideMarker {
},
);

// Position the marker beyond the inline start of the border box list item. This needs to
// take into account the border of the item.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But also the padding, right? I guess it's fine for now since it's tricky to resolve the percentage, but the comment should mention it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, right, of course. I've gone back to using PaddingBorderMargin here and taking into account padding. I've also left a comment explaining that the containing block used here is the wrong one and what is wrong about the results.

Comment on lines 1788 to 1803
// `self.current_block_direction_position` can be negative here, so we cannot max with zero.
let block_size_from_marker = self
.marker_block_size
.unwrap_or(self.current_block_direction_position);
let total_block_size = self
.current_block_direction_position
.max(block_size_from_marker)
.into();

// If this is a list item (even empty) with an outside marker, then it
// should not collapse through.
let collapsed_through = match self.marker_block_size {
Some(_) => false,
None => self.next_in_flow_margin_collapses_with_parent_start_margin,
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems a bit strange to take the maximum of the same value when there is no marker. The logic can bemoved into the match:

Suggested change
// `self.current_block_direction_position` can be negative here, so we cannot max with zero.
let block_size_from_marker = self
.marker_block_size
.unwrap_or(self.current_block_direction_position);
let total_block_size = self
.current_block_direction_position
.max(block_size_from_marker)
.into();
// If this is a list item (even empty) with an outside marker, then it
// should not collapse through.
let collapsed_through = match self.marker_block_size {
Some(_) => false,
None => self.next_in_flow_margin_collapses_with_parent_start_margin,
};
let (total_block_size, collapsed_through) = match self.marker_block_size {
Some(marker_block_size) => (
self.current_block_direction_position.max(marker_block_size),
false,
),
None => (
self.current_block_direction_position,
self.next_in_flow_margin_collapses_with_parent_start_margin,
),
};

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. Done.

@mrobinson mrobinson added this pull request to the merge queue Apr 29, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Apr 29, 2024
While <https://drafts.csswg.org/css-lists/#list-style-position-property> says:

> The size or contents of the marker box may affect the height of the
> principal block box and/or the height of its first line box, and in some
> cases may cause the creation of a new line box; this interaction is also
> not defined.

All other browsers ensure that the first line of list item content is
the same block size as the marker. Doing this is complicated, but we can
ensure that the entire list item is at least as tall as the marker. This
should handle the majority of cases and we can make refinements later
for stranger situations, such as when the marker is very tall.

Co-authored-by: Oriol Brufau <obrufau@igalia.com>
@mrobinson
Copy link
Member Author

/css/CSS2/text/text-indent-applies-to-003.xht is now failing because a text-indent is applied to the list item which should also cause the marker to be offset even more.

@mrobinson mrobinson added this pull request to the merge queue Apr 29, 2024
Merged via the queue into servo:main with commit f68a2e7 Apr 29, 2024
9 checks passed
@mrobinson mrobinson deleted the empty-list-item branch April 29, 2024 18:29
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

Successfully merging this pull request may close these issues.

None yet

2 participants