The renderer/core/layout
directory contains the implementation of layout objects. It covers the following document lifecycle states:
InLayoutSubtreeChange
and LayoutSubtreeChangeClean
)InPreLayout
)InPerformLayout
)AfterPerformLayout
and LayoutClean
)See LayoutNG for the implementation details.
The layout code is maintained by the layout team.
The CSS box model is based on a series of nested boxes, from outside to inside:
LayoutBox
When there are non-overlay scrollbars, according to css-overflow-3, they should be inserted between the inner border edge and the outer padding edge.
The following graph is modified from the graph in the css box model spec, showing scrollbars:
|-------------------------------------------------| | | | margin-top | | | | |---------------------------------------| | | | | | | | border-top | | | | | | | | |--------------------------|--| | | | | | | | | | | | | padding-top |##| | | | | | |##| | | | | | |----------------| |##| | | | | | | | | | | | | ML | BL | PL | content box | PR |SW| BR | MR | | | | | | | | | | | | | |----------------| | | | | | | | | | | | | | | padding-bottom | | | | | | | | | | | | | |--------------------------|--| | | | | | scrollbar height ####|SC| | | | | |-----------------------------| | | | | | | | | border-bottom | | | | | | | |---------------------------------------| | | | | margin-bottom | | | |-------------------------------------------------| BL = border-left BR = border-right ML = margin-left MR = margin-right PL = padding-left PR = padding-right SC = scroll corner SW = scrollbar width
Note that the vertical scrollbar (if existing) will be on the left in right-to-left direction horizontal writing-mode. The horizontal scrollbar (if existing) is always at the bottom.
When a LayoutBox has scrollable overflow, it is associated with a PaintLayerScrollableArea. PaintLayerScrollableArea uses a “scroll origin” to represent the location of the top/left corner of the content rect (the visible part of the content) in the coordinate system defined by the top/left corner of the overflow rect, when the box is scrolled all the way to the beginning of its content.
For content which flows left-to-right and top-to-bottom, the scroll origin will be (0, 0), i.e., the top/left of the content rect is coincident with the top/left of the overflow rect when the box is scrolled all the way to the beginning of content.
For content which flows right-to-left (including direction:ltr, writing-mode:vertical-rl, and flex-direction:row-reverse), the x-coordinate of the scroll origin will be positive; and for content which flows bottom-to-top (e.g., flex-direction:column-reverse and vertical writing-mode with direction:ltr), the y-coordinate of the scroll origin will be positive.
In all cases, the term ‘scrollOffset’ (or just ‘offset’) is used to represent the distance of the scrolling viewport from its location when scrolled to the beginning of content, and it uses type ScrollOffset. The term ‘scrollPosition’ (or just ‘position’) represents a point in the coordinate space defined by the overflow rect, and it uses type gfx::PointF.
For illustrations of these concepts, see these files:
doc/ltr-tb-scroll.png doc/rtl-bt-scroll.png doc/rtl-tb-scroll.png
When computing the scroll origin, if the box is laid out right-to-left and it has a scrollbar for the orthogonal direction (e.g., a vertical scrollbar in a direction:rtl block), the size of the scrollbar must be added to the scroll origin calculation. Here are two examples -- note that it doesn't matter whether the vertical scrollbar is placed on the right or left of the box (the vertical scrollbar is the |/|
part):
content rect |<-------->| scroll origin |----------->| _______________________ | |/| | | |/| | | |/| | direction:rtl | |/| box | | |/| | | |/| | |__________|/|__________| overflow rect |<--------------------->| content rect |<-------->| scroll origin |----------->| _________________________ | | |/| | | |/| | | |/| writing-mode: | | box |/| vertical-rl | | |/| | | |/| |____________|__________|/| overflow rect |<--------------------->|
Layout and Paint work with and frequently refer to four coordinate spaces (really two, with two variants):
Physical coordinates: Corresponds to physical direction of the output per the physical display (screen, printed page). Generally used for painting, thus layout logic that feeds into paint may produce values in this space. CSS properties such as top
, right
, bottom
, and left
are in this space.
Logical coordinates: Used in layout to allow for generalized positioning that fits with whatever the writing-mode
and direction
CSS property values may be. Properties named with before
, after
, start
or end
are in this space. These are also known respectively as ‘logical top’, ‘logical bottom’, ‘logical left’, and ‘logical right’.
Logical coordinates without flipping inline direction: those are “logical block coordinates”, without considering text direction. Examples are “LogicalLeft” and “LogicalRight”.
Example with writing-mode: vertical-rl; direction: ltr
:
'top' / 'start' side block-flow direction <------------------------------------ | ------------------------------------- | | c | s | | 'left' | o | o | | inline 'right' / | n | m | | direction / 'after' | t | e | | 'before' side | e | | | side | n | | | | t | | | ------------------------------------- v 'bottom' / 'end' side
Another example -- consider a relative-positioned element:
<style> html { writing-mode: vertical-rl; } </style> <div id="container" style="background-color: lightBlue; width: 300px; height: 200px;"> <div id="relpos" style="position: relative; top: 50px; left: -60px; width: 70px; height: 80px; background-color: red;"></div> </div>
The final location of these within an 800x600 frame is as:
container: (492, 8 300x200) relpos: (662, 58 70x80)
The 8px is the default margin of HTML body element per https://html.spec.whatwg.org/multipage/rendering.html#the-page, which is specified in ../html/resources/html.css.
See the diagram for full detail on dimensions of the involved elements.
For more examples of writing mode and direction combinations, see this demo page though note horizontal-bt
is obsolete.
Note there are two primary similar, but slightly different, methods regarding finding the containing block for an element:
LayoutObject::Container()
which returns the containing block for an element as defined by CSS.LayoutObject::ContainingBlock()
which returns the enclosing non-anonymous block for an element. If the containing block is a relatively positioned inline, it returns that inline's enclosing non-anonymous block.There are other containing block methods in LayoutObject
for special purposes such as fixed position, absolute position, and paint invalidation. Code will sometimes just refer to the ‘containing’ element, which is an unfortunately ambiguous term. Paying close attention to which method was used to obtain the containing element is important.
TODO(wkorman): Elaborate on:
mapToVisualRectInAncestorSpace()
mapAncestorToLocal()
Widget
and FrameView
trees. Note the former will be done away with at some point per http://crbug.com/637460.GeometryMapper
(or just point to its section in paint README). For now, see the Web page geometries design document.TODO(wkorman): Provide an overview of scrolling. For now, the BlinkOn talk on Scrolling in Blink is a good overview.
Root layer scrolling is an ongoing refactoring of Blink's scrolling architecture, which makes the root PaintLayer
responsible for the scrolling that was previously done by FrameView
. For more details, see: Root Layer Scrolling.
Here we provide a brief overview of key terms relevant to box flow, inline flow, and text orientation. For more detail see CSS Writing Modes Level 3.
The CSS Logical Properties Level 1 specification represents the latest CSSWG thinking on logical coordinate space naming. CSSWG has standardized on block-start
, block-end
, inline-start
, and inline-end
, or just start
and end
when the axis is either implied or irrelevant.
Note that much of the Blink code base predates the logical properties specification and so does not yet reference logical direction consistently in the stated manner, though we would like to head in that direction over time. See also the physical, flow-relative, and line-relative abstract box terminology specification.
writing-mode
: either horizontal or vertical, with vertical having either left-to-right or right-to-left block flow. Geometry is transposed for vertical writing mode. See calls to transposed{Rect,Point,Size}()
.direction
/dir
: “inline base direction” of a box. One of ltr
or rtl
. See calls to isLeftToRightDirection()
.text-orientation
: orientation of text in a line. Only relevant for vertical modes.