GNOME Bugzilla – Bug 610879
Support percentages in CSS's width/height attributes
Last modified: 2017-11-01 10:58:46 UTC
Currently the only way to specify a width or height in CSS is absolute i.e by providing a pixel value like "100 px". This has the downside that he have to make assumptions about the screen size which cannot be correct for all cases. 100px aren't the same on a 1920x1080px screen and on an 1280x600 (netbook) screen. The obvious solution would be to have a way to specify relative values like "10%", this would have the advantage that we don't have to know the screen dimensions beforehand and the same code would work on different screen resolutions (i.e we don't end up with parts of the UI being off screen only because it runs on another device). The problem with doing this is that in most cases the size of an element depends on the size of the children, in which case there is no way to calculate the size based on relative values (chicken/egg problem). We are hitting undefined territory here as the CSS spec says: "Specifies a percentage width. The percentage is calculated with respect to the width of the generated box's containing block. If the containing block's width depends on this element's width, then the resulting layout is undefined in CSS 2.1." [1] Same goes for height (sightly different): "Specifies a percentage height. The percentage is calculated with respect to the height of the generated box's containing block. If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the value computes to 'auto'. A percentage height on the root element is relative to the initial containing block. " [2] But the problem is basically the same: When we don't know the size of the "containing block" because it depends on the size of the inner elements, the behavior is undefined in the spec. So to solve this I propose the following behavior: 1) When the "containing block" (parent) has a fixed size (independent from it's children), just use this as a base for the calculation. 2) For the undefined case (size of the parent depends on the child's size), we can either: a) By pass the parent and find the first ancestor with a fixed size and use this as base or b) Use the size of the stage as a base in this case This way we would have an easy way to fix the size problems mentioned above, but at the cost of relying on non standard CSS behavior. 1: http://www.w3.org/TR/CSS21/visudet.html#the-width-property 2: http://www.w3.org/TR/CSS21/visudet.html#the-height-property
It should be implemented with 'top', 'right', 'bottom', 'left' properties. http://www.w3.org/TR/CSS21/visuren.html#propdef-top I think We can modify only StBin. remove from it x_fill, y_ fill, x_align, y_align properties and use top..., width, height.
> 2) For the undefined case (size of the parent depends on the child's size), we > can either: > a) By pass the parent and find the first ancestor with a fixed size and > use this as base or > b) Use the size of the stage as a base in this case Mmmh, IMHO stepping up the hierarchy until a fixed-sized element is found seems the most reasonable (note that this is purely from a CSS perspective, it might be horrible to implement, a complete performance hog and kitten killer) (In reply to comment #1) > It should be implemented with 'top', 'right', 'bottom', 'left' properties. No. Those define the position of the element, not its dimensions. > http://www.w3.org/TR/CSS21/visuren.html#propdef-top > > I think We can modify only StBin. remove from it x_fill, y_ fill, x_align, > y_align properties and use top..., width, height. left = x0, top = y0 right = x1, bottom = y1 Changing the meaning of those to anything else would be completely confusing IMO.
> (In reply to comment #1) > > It should be implemented with 'top', 'right', 'bottom', 'left' properties. > > No. Those define the position of the element, not its dimensions. Yes, it is. Where element with width x% should be position? We have 100 - x% free space, so need position element in it.
(In reply to comment #3) > > (In reply to comment #1) > > > It should be implemented with 'top', 'right', 'bottom', 'left' properties. > > > > No. Those define the position of the element, not its dimensions. > > Yes, it is. Where element with width x% should be position? We have 100 - x% > free space, so need position element in it. Mmmh, that's a different question, right? Currently, all positioning is done in the code (read: we don't support top, right, bottom & left at all, neither with fixed values, nor with percentages) - width/height on the other hand are supported, but only with fixed sizes. If I understand the scope of this bug report correctly, it asks for something like replacing: .all-app { border-radius: 10px; ... height: 400px; } with: .all-app { border-radius: 10px; ... height: 60%; } Where 60% would probably refer to the screen height in this case. So in theory it's just the same as changing 400px to 750px - it does not affect the code which positions the element on the screen at all. The only difference is that it's completely clear what 750px are, but we cannot say the same for 60% (we have to figure out what 100% refers to). I think positions in CSS are a completely different beast - and I don't think we should allow themes to position anything at will. If I misunderstood you and what you really want is setting x_fill, y_fill etc from CSS, then we should invent our own property names (e.g. x-fill, y-fill) rather than changing the meaning of existing properties, which would be completely confusing.
So, the clutter allocation model is bottom-up and pixel-based, so there's no way for an actor to request "50%". To do that we'd have to bypass the ordinary size-request/allocation system when percentage lengths were in use. Probably something like: In _st_actor_get_preferred_width(): If the parent has a fixed width (ie, natural_width_set == TRUE) and the child has a percentage width specified in the CSS, then return the minimum of the actor's natural_width and the CSS-specified width (parent-fixed-width * css-percentage) In _st_actor_get_preferred_width(): contrariwise In _st_allocate_fill(): If the child has a percentage width specified, then don't allocate it more than (parent-allocated-width * css-percentage). Likewise with height. In the well-defined case (parent has a fixed width), this should do the right thing always (because parent-allocated-width will be the same as parent-fixed-width, so we'll have used the same width at request time as we use at allocation time). If the parent doesn't have a fixed width, then the child may unexpectedly get less width than it was expecting, which will be fine if the child is something like an icon, but not if it's something like a multiline ClutterText. So, uh, don't do that.
One thing to note here is that in CSS, the "containing block" - the thing that percentage sizes are relative to - is not always the parent element. For absolute positioned elements it is the nearest *positioned* ancestor (that is, with 'position' as 'absolute' 'relative' or 'fixed'.) So it's not absolutely out of line to make percentage sizes relative to some more distant ancestor - or we could even make them always stage relative. Would it be possible to do a reasonable implementation of percentage sizes only at the allocate() step? Note that since percentage sizes only make sense when the parent has a fixed size independent of the children, we really don't care what natural size the child reports before then - it could be the percentage size, it could be the child's normal natural size. And we generally don't want percentage sizes to override the minimum size - the minimum size is a minimum size. So, basically the idea would be that we'd have a _st_actor_get_preferred_height/width_at_allocation() that took the allocated size of the parent as an extra argument. (With typical CSS nasties about whether that size is the content size or the total size of the parent... for consistency with CSS it probably would want to be the total size of the parent including borders and margins with a need to add an intermediate container if you you want to just have a percentage of the content area) This would certainly require us to go ahead and add StGroup. And we'd have to be careful that there are no assumptions in StTable and StBoxLayout that the children natural sizes don't change between get_preferred_height() and allocate().
This is an old bug that hasn't seen any activity for a while. Is it really needed?
(In reply to Allan Day from comment #7) > Is it really needed? I guess not since there was no response for three years. Closing, feel free to reopen if you actually have an explanation as to why it should be implemented.