auto
An Adventure in LayoutStyle computation is per element, depth-first traversal of all dirty elements.
End result: exactly one value per property per element.
{1} DOM Element → {0,1,2} CSS Boxes
| # Boxes | display
|
|---|---|
| 0 | none, contents
|
| 1 | all other values |
| 2 | table, list-item
|
End result: zero or more boxes per element.
{1} CSS Box → 1+ Box Fragments
Fragmentation = line breaking, page breaking, column breaking, region breaking, etc.
We're not going to talk about fragmentation.
The goal of layout is to fill in the correct values
for x, y, width, and height for all boxes in the tree.
Origin coords are relative to parent origin.
~10K lines of code, i.e. we're simplifying this next slide a lot.
VeryBasicLayoutBox::Reflow() {
CalculateMyWidth();
positionOfNextChild = 0;
for each child in childList {
“Yo, I'm this wide. What size do you wanna be?” — me
“I wanna be this big.” — child
“Okay, I'm gonna put you here.” — me
positionOfNextChild += child.size;
}
CalculateMyHeight();
}
VeryBasicLayoutBox::Reflow() {
CalculateMyWidth();
positionOfNextChild = 0;
for each child in childList {
“Yo, I'm this wide. What size do you wanna be?” — me
“I wanna be this big.” — child
“Okay, I'm gonna put you here.” — me
positionOfNextChild += child.size;
}
CalculateMyHeight();
}
VeryBasicLayoutBox::Reflow() {
CalculateMyWidth();
positionOfNextChild = 0;
for each child in childList {
“Yo, I'm this wide. What size do you wanna be?” — me
“I wanna be this big.” — child
“Okay, I'm gonna put you here.” — me
positionOfNextChild += child.size;
}
CalculateMyHeight();
}
VeryBasicLayoutBox::Reflow() {
CalculateMyWidth();
positionOfNextChild = 0;
for each child in childList {
“Yo, I'm this wide. What size do you wanna be?” — me
“I wanna be this big.” — child
“Okay, I'm gonna put you here.” — me
positionOfNextChild += child.size;
}
CalculateMyHeight();
}
VeryBasicLayoutBox::Reflow() {
CalculateMyWidth();
positionOfNextChild = 0;
for each child in childList {
“Yo, I'm this wide. What size do you wanna be?” — me
“I wanna be this big.” — child
“Okay, I'm gonna put you here.” — me
positionOfNextChild += child.size;
}
CalculateMyHeight();
}
VeryBasicLayoutBox::Reflow() {
CalculateMyWidth();
positionOfNextChild = 0
for each child in childList {
“Yo, I'm this wide. What size do you wanna be?” — me
“I wanna be this big.” — child
“Okay, I'm gonna put you here.” — me
positionOfNextChild += child.size;
}
CalculateMyHeight();
}
VeryBasicLayoutBox::CalculateMyWidth() {
if mStyleContext.width == auto {
mRect.width = mParent.width - border - padding - margin;
}
else { // fixed size
mRect.width = mStyleContext.width;
}
}
VeryBasicLayoutBox::CalculateMyHeight() {
if mStyleContext.height == auto {
mRect.height = positionOfNextChild;
}
else { // fixed size
mRect.height = mStyleContext.height;
}
}
Works great... until we start to put things side-by-side.
“CSS [spec] editing: expect 80% of the time to be spent defining what 'auto' does and does not do and you'll do fine.” — Sylvain Galineau
auto: Sizing Primitivespx, pt, pc, in, cm, mm
em, ch, rem, vw, vh, vmin, vmax
%) sizing
containingBlock.width×percentage − (borders + padding + margins)
min-content
max-content
auto: Compound Sizingfit-content aka shrink-to-fit
flex
fit-content aka shrink-to-fit
max(
min(max-content, /* Be as wide as the content but no wider */
fill-available), /* But avoid overflowing the containing block */
min-content) /* And definitely don't let any content overflow */
)
flex
basis + flex ratio × (fill-available − ∑basis)
auto: Sizing Constraintsmin/max-width/height
auto: What is auto?fill
min-size, flex-basis + flex×free space)
auto: Why is it auto?auto: Flexboxflex-basis: auto;
flex-grow: 0;
flex-shrink: 1;
min-width: auto;
With great power comes great responsibility.
order or positioningWhat is your sizing based on?
em or rem.
em or ch.
auto or min-content/max-content.
flex, min-width, max-width, etc.
Absolute units are usually the wrong answer.
WARNING: Requires Critical Thinking
Set media query breakpoints in em or ch, not always in px.
Use shorthands. Protect yourself against invading rules!
.lowSpecificity { background: linear-gradient(red, maroon); }
/* … more stuff … */
#highSpecificity { background-color: green; }
Unless you're intentionally wanting a longhand to cascade in from somewhere else, use the shorthand to give you a blank slate.
background: url(…) top left, url(…) bottom right, url(…) center; background-repeat: no-repeat
ems.
direction or unicode-bidi.
dir attribute, because it's content, not style (and you can then use :dir() selectors).