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

Ladybird text input display issue #23915

Open
jordanmartell0 opened this issue Apr 10, 2024 · 7 comments
Open

Ladybird text input display issue #23915

jordanmartell0 opened this issue Apr 10, 2024 · 7 comments
Labels
bug Something isn't working has-repro We have a way to reproduce this bug. reduction-of-web-content Issue has a simplified reduction based on real-world web content. student project

Comments

@jordanmartell0
Copy link

Hello, I'm a University of Utah student working on Ladybird as part of my final project for CS 4560 Web Browser Internals. While using the browser, I found a bug in how it displays a search bar of certain web pages, specifically the length of the search bar (pictured below are how Chrome displays the search bar and how Ladybird displays the same search bar)

Chrome:

image

Ladybird:

image

I minimized the bug down to this simple html and css. Screenshots of how Chrome and Ladybird render this webpage are below

<style>
  .sb-input{
    width:100%;
  }
  .sb-nav__secondary{
    position:absolute;
  }
</style>
<div class="sb-nav__secondary">
      <input class="sb-input"/>
</div>

Chrome:

image

Ladybird:

image

I am interested in taking a stab at resolving this issue. I am not super familiar with the code yet, but I’d appreciate any pointers on how to proceed if anyone has ideas, thanks!

@jordanmartell0 jordanmartell0 changed the title Ladybird column display issue (column-width css) Ladybird text input display issue Apr 10, 2024
@ADKaster ADKaster added bug Something isn't working has-repro We have a way to reproduce this bug. reduction-of-web-content Issue has a simplified reduction based on real-world web content. labels Apr 10, 2024
@kalenikaliaksandr
Copy link
Contributor

kalenikaliaksandr commented Apr 10, 2024

both <input> and element wrapping it create block formatting context (BFC). you could find that information by checking a dump of layout tree:

6847189.053 WebContent(39357): Viewport <#document> at (0,0) content-size 1321x836 [0+0+0 1321 0+0+0] [0+0+0 836 0+0+0] children: not-inline
  BlockContainer <html> at (0,0) content-size 1321x836 [0+0+0 1321 0+0+0] [0+0+0 836 0+0+0] [BFC] children: not-inline
    BlockContainer <body> at (8,8) content-size 1305x0 [8+0+0 1305 0+0+8] [8+0+0 0 0+0+8] children: inline
      BlockContainer <div.sb-nav__secondary> at (8,8) content-size 6x22 positioned [0+0+0 6 0+0+0] [0+0+0 22 0+0+0] [BFC] children: inline
        frag 0 from BlockContainer start: 0, length: 0, rect: [9,9 4x20] baseline: 22
        TextNode <#text>
        BlockContainer <input.sb-input> at (9,9) content-size 4x20 inline-block [0+1+0 4 0+1+0] [0+1+0 20 0+1+0] [BFC] children: not-inline
          Box <div> at (11,10) content-size 0x18 flex-container(row) [0+0+2 0 2+0+0] [0+0+1 18 1+0+0] [FFC] children: not-inline
            BlockContainer <div> at (11,10) content-size 0x18 flex-item [0+0+0 0 0+0+0] [0+0+0 18 0+0+0] [BFC] children: inline
              TextNode <#text>
        TextNode <#text>
      TextNode <#text>

input has display: inline-block because of default.css so it sized in InlineFormattingContext::dimension_box_on_line()

a good next step for fixing the bug might be to find out why BFC and IFC end up assigning wrong width.

@pavpanchekha
Copy link

Random guess... Does putting the parent in absolute position trigger shrink to fit layout? Then the width: 100% doesn't resolve correctly because the parent width is not set yet? So it ends up set to 0?

@awesomekling
Copy link
Member

I think this happens because of the following mechanism in HTMLInputElement::adjust_computed_style():

    if (type_state() != TypeAttributeState::FileUpload) {
        if (style.property(CSS::PropertyID::Width)->has_auto())
            style.set_property(CSS::PropertyID::Width, CSS::LengthStyleValue::create(CSS::Length(size(), CSS::Length::Type::Ch)));
    }

For input elements with a non-auto CSS width computed value, we take the HTMLInputElement::size() value and turn it into a CSS length with unit ch.

In your repro above, there's no size attribute on the input element, so we default to 20 per the spec.

Because there is also a width: 100% (non-auto) that applies to the input element, we just bypass the mechanism that would give us 20ch.

Note that HTMLInputElement::adjust_computed_style is a totally ad-hoc mechanism and not something from the spec. We needed a way to turn the size attribute into width: Nch and this is it. Sounds like we need to think of a better way!

@awesomekling
Copy link
Member

One possible approach to this would be to let input elements have a natural/intrinsic layout size, derived from the size attribute and defaulting to 20ch. That would require special-casing input elements in layout width calculation.

@jordanmartell0
Copy link
Author

Thank you all for the ideas! My team and I have started working on this issue and we found that moving the line

style.set_property(CSS::PropertyID::Width, CSS::LengthStyleValue::create(CSS::Length(size(), CSS::Length::Type::Ch)));

up out of the if statement fixes the specific web page in the original post. However, this obviously causes a lot of text inputs on other web pages to be formatted incorrectly. We are trying to add an if statement to the beginning of the adjust_computed_style method, something like

if (parent HTML element has position CSS property and position value is 'absolute')
   style.set_property(CSS::PropertyID::Width, CSS::LengthStyleValue::create(CSS::Length(size(), CSS::Length::Type::Ch)));

however, we haven't found a way to access the parent HTML element nor its stylings in the adjust_computed_style method. If that approach seems reasonable, any advice on that would be appreciated.

We also looked into the idea mentioned in the post right before this ("special-casing input elements in layout width calculation."), but we haven't found where exactly the layout width calculator presently takes place, so if that approach is preferred we'd appreciate any direction on where to look for that.

Thank you again for your help!

@awesomekling
Copy link
Member

This is definitely a non-trivial issue, perhaps not suitable for newcomers to the codebase.

Width calculation is not performed in a single location in layout, there are many different places and ways we determine widths, depending on a number of circumstances (which formatting context is used, the type of box being sized, etc)

One way that might work is to piggyback on replaced element layout by making box_is_sized_as_replaced_element() return true for boxes representing input elements. We would then also need those boxes to be assigned natural width and height somehow (via set_natural_width and set_natural_height so that they can get the <size>ch width and 1lh height you'd expect from <input type=text>

This specific behavior makes sense for text-based input elements, but we'd need different behavior for <input type=button>, <input type=image> etc.

@pavpanchekha
Copy link

Thanks @awesomekling, we'll try that. It seems to make sense, input elements usually are rendered as replaced content with natural width and height on other OSes. Buttons and images are too but agreed that it's less clear exactly how big those should be.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working has-repro We have a way to reproduce this bug. reduction-of-web-content Issue has a simplified reduction based on real-world web content. student project
Projects
None yet
Development

No branches or pull requests

5 participants