CSS
Fundamentals Recap
- Inspector
- Can force element states
- Shift click colour property changes representation
- Firefox has a info icon on some properties to tell you why they're ignored
Rendering logic
-
user-agent stylesheet
- HTML tags include minimal styles
- e.g.
<a>
in chrome 86a { color: -webkit-link; cursor: pointer; text-decoration: underline; }
- Used to be common to use a CSS reset to remove default styles
- More consistent these days
-
Inheritance
- Certain CSS properties inherit
- Most inheritable properties are typography-related: color, font-size, text-shadow, etc...
-
Forcing inheritance
- Sometimes may want to force inheritance, e.g. link colors
- Even though color is inherited it's being overwritten by the default style
a { color: inherit; }
- Cascade
- Which rule is followed when multiple apply
- Specificity
- e.g. IDs are more specific than tags which are more specific than classes
- Mostly avoid this by having styles tied to components
- Block and inline directions
- Words are combined into blocks, like headings and paragraphs
- Pages are constructed out of blocks
- Documents have 2 "directions"
- Vertically oriented blocks
- Horizontally oriented words
- Block elements stack vertically
- Inline elements go across
- Logical properties
- Built in style for
<p>
tags in chromep { display: block; margin-block-start: 1em; margin-block-end: 1em; margin-inline-start: 0px; margin-inline-end: 0px; }
- Equivalent to
margin-top
,margin-bottom
,margin-left
,margin-right
for english - Different for e.g. right to left languages
- Designed to replace conventional alternatives
- Built in style for
-
Box model
- Aspects
- Content
- Padding
- Border
- margin
- Inspector
- Orange box - margin
- Yellow box - border
- Green box - padding
- Blue box - content
- Box sizing
box-sizing
propertycontent-box
Only takes inner content into accountborder-box
Is more intuitive- With
content-box
,width: 100%
means the content fills the parent and the border and padding are added on top - Can set as the default for every element
*, *::before, *::after { box-sizing: border-box; }
*
selects all elements, but before, after aren't elements
- Padding
- Inner space
- Receives background colour
- Units
- px
- em, relative to font size
- rem
- percentages, calculated based on element's available width (even for top, bottom)
- Shorthand
- two values: first value is top/bottom, second is left/right
- four values: top, right, bottom left
- clockwise
- three values: top, right/left, bottom
- long form values overwrite shorthand, have to come after
.box { padding: 48px; padding-bottom: 0; }
- Border
- Styles specific to border
-
border-width
-
border-style
-
border-color
-
- Shorthand
-
border 3px solid hotpink;
-
- Only required field is
border-style
, otherwise no border - If colour isn't specified uses font's colour
currentColor
is a reference to the element's derived text colour, can be used anywhere a colour can-
border-radius
- really
corder-radius
- Rounds element even if no border
- Accepts directional values like padding
- really
- Outline
- Doesn't affect layout
- More like box shadow, cosmetic effect
- Stacked outside border and can be used as a second border effect
- will follow curve set with
border-radius
in all browsers except safari (after sept 2021) outline-offset
property, gap between element and outline- Sometimes used as focus indicators
- Styles specific to border
- Margin
- Space around element
- Negative margin
- Can pull element outside its parent
- Can pull siblings closer
- Changes gap between elements, causing others to move
- Affects position of all siblings
- Auto margin
- Seeks maximum available space
- top/bottom auto is equivalent to 0
- Only works with explicit width
- Centre child in container
margin-left: auto; margin-right: auto;
- Stretched content
-
Images aren't part of the DOM, foreign object embedded
-
If not given a width takes up its natural size
- Have to use
width:100%
on image - but calculation won't account for the negative margin
- Have to use
-
Use a wrapping element instead of using img (or video, etc...) for layout
.stretched { margin-left: -32px; margin-right: -32px; }
-
- Flow layout
- Every HTML element will have its layout calculated by a layout algorithm, called layout modes
- 7 distinct ones
- Flow layout is default
- Document type layouts
- Elements
- Block
- Inline
- Can toggle element type with
display:
property - Inline
- Can shift in inline direction with margin-left, margin-right
- Can't give width, height
- Replaced elements (img, video, canvas, etc...) are an exception
- Can take explicit dimensions, margin-top, etc...
- Like a foreign object in a inline wrapper, those properties apply to the foreign object
- Have extra space from
line-height
- Whitespace creates gaps between elements
- Use flex
- Can line wrap
- text
- What would vertical margin even mean in this case - not available
- still one shape, e.g. border goes around wrapped text
- Block
- Expand to fill entire horizontal space
-
width: fit-content;
- Still doesn't allow anything else on the whole inline row
- Inline-block
- Block level element that can be placed in an inline context
- Treated as inline for layout, internally acts more like block
- e.g. make text element inline block, has access to more properties such as width, margin-top
- Doesn't line wrap
- Width algorithms
- Percentage widths are based on the parent element's content space
- Also set content width, not including margin i.e. margin will be out of parent
- Default block element width is
auto
not100%
- Grows as much as it can
- margin will fit in parent
- Kinds of values
- Measurements: %, px, rem
- Explicit or relative to parent's available space
- Keywords: auto, fit-content
- Different behaviour depending on context
- Measurements: %, px, rem
-
min-content
- As narrow as it can be based on child contents
- Intrinsic value
-
max-content
-
fit-content
- If content fits in parent behaves like
max-content
- Otherwise adds line breaks as needed
- If content fits in parent behaves like
min-width
,max-width
- Constraints - Can specify constraints in pixels with a percentage width- Max width wrapper
- Constrain element to sit in a centered column
- Fills available space on smaller viewports
- Sets a max width
- Horizontally center itself in parent if there's enough space
- Horizontal "breathing room" so children aren't right up against viewport
.max-width-wrapper { max-width: 350px; margin: auto; padding-left: 16px; padding-right: 16px; }
- Need to wrap card to put padding space around card
- Percentage widths are based on the parent element's content space
- Height algorithms
- Default width for block elements is as much as possible, height is as little as possible while fitting
- Height is typically more dynamic, don't usually set a max height
- Expect to be longer on small phone screens and shorter on desktops - text wrapping
- Element that wraps around entire app
min-height: 100%;
doesn't work- Percentage is based on parent height
- Parent tags with default behaviour take the least height possible
- Put
height: 100%
on every element before main one, includinghtml
,body
- By default width looks up the tree - based on parent size
- Height looks down - based on children
- Margin collapse
-
Margins that a side by side can share space
<style> p { margin-top: 24px; margin-bottom: 24px; } </style> <p>Paragraph One</p> <p>Paragraph Two</p>
-
Will be 24px between, not 48
-
Early CSS wasn't intended for layouts - documents, headings, paragraphs
-
Rules
- Only vertical margins collapse
- Can change writing-mode so blocks stack horizontally - flips this rule
- Margins only collapse in flow layout
- Only ajacent margins collapse
<style> p { margin-top: 32px; margin-bottom: 32px; } </style> <p>Paragraph One</p> <br /> <p>Paragraph Two</p>
- Will not collapse
- Bigger margin wins, smaller is completely collapsed inside larger
- Nesting doesn't prevent collapse
<style> p { margin-top: 48px; margin-bottom: 48px; } </style> <div> <p>Paragraph One</p> </div> <p>Paragraph Two</p>
- Will collapse
- Intended to increase distance between siblings, not parent/child - use padding for that
- Will always try to increase padding between siblings even if it means transferring margin to parent
- Margins need to touch to collapse
- Blocked by padding/boarder
- Blocked by a gap
- Blocked by a scroll container (overflow)
- Can collapse in the same direction
<style> .parent { margin-top: 72px; } .child { margin-top: 24px; } </style> <div class="parent"> <p class="child">Paragraph One</p> </div>
- Child margin absorbed into parent
- More than 2 margins can collapse (e.g. adjacent items and their parents)
- Negative margins collapse - most negative wins
- Positive and negative margins cancel
- Multiple positive and negative
- Positive collapse, negatives collapse, add numbers to cancel
-
Avoid margins at component boundaries
-
Layout components
-
- Positioned layout
- Items can overlap
position
property: relative, absolute, fixed, sticky- Default is static - not positioned, some other layout mode
- Relative
- Constrains certain children
- Enables additional CSS
- top, left, right, down
- Push the element around
- Doesn't affect layout, unlike margin (margin will affect neighbours, margin will dynamically resize)
- Can be applied to both block and inline
- Absolute
- Not in flow
- UI elements that need to float above the UI - tooltips, dropdowns
- Decorative elements that need to be stuck in certain positions
- Stacking multiple elements in the same place like a deck of cards
- Adjusted based on container, not in flow position
- Default placement: if no anchor than uses in flow position (except without line wrapping, and will stack)
- Effect on layout
- Pulls it out of flow
- Browser considers space empty
<style> p { position: absolute; } <p>This is a paragraph.</p> <p>Another paragraph, with different words.</p> <p>Finally, to complete the set, a third.</p>
- Paragraphs will stack
- Will shrink to fit the content
- Centering trick
- Setting the same distance from each edge centres the element (in containing block, see below)
- If you specify width,height it prioritizes top,left and ignores bottom,right
- auto margins, moves to the centre
- Flow only expands margins left and right, absolute expands all
.box { position: absolute; top: 0px; left: 0px; right: 0px; bottom: 0px; width: 100px; height: 100px; margin: auto; background: deeppink; }
- Can use
inset: 0;
instead of specifying directions individually
-
Containing blocks
- Every HTML element has a containing block
- Rectangle that forms the bounds of the element's container
- containing block is the size and shape of the parent element's content box
- Absolute positions element based on containing block
- But if we can go outside the parent, how is it calculated
- Can only be contained by other elements using positioned layout
- If no positioned parent uses a box the size of the viewport
- Absolute elements ignore padding - taken out of flow
-
Borders
- Box element needs to be relative so that it constrains absolute children - relative will still flow
-
Rounding border
- Percentage border radius makes the box circular
- For a text bubble the radius should depend on the height which depends on the font size
- Use
rem
-
Stacking contexts
- Which overlapping element renders on top depends on layout mode
- Flow overlap can be forced by negative margin
- Later dom nodes are rendered after and are on top
- Content is painted separately from the background
- Back boxes content will be drawn over top box's background
- If you want layered elements probably want to use positioned layouts
- Positioned elements will render on top of non-positioned ones
- If both are positioned later elements will be drawn last - no background issue
- z-index
- Only works with positioned (and flex, grid)
- Higher z-index = closer to viewer
- Default is auto = 0
- Negative tend to introduce additional complexity without much benefit
- Not compared across application
- Only within stacking context
- Creating new contexts
- Combining a non-static position with a z-index
- Setting opacity less than 1
- Setting position to fixed or sticky
- applying mix-blend-mode other than normal
- Adding z-index to a child inside flex or grid
- Using transform, filter, clip-path or perspective
- Explicitly creating a context with
isolation: isolate
- Debugging
- CSS Stacking Context Inspector browser extension
- z-index wars
- element is rendering behind another but want it to be in front
- Keep increasing z-index of stuff until it seems to work
- Alternatives
- Swapping DOM order
- Not always appropriate, will change order in the tab index - problem for interactive elements
- Swapping DOM order
- Isolated stacking contexts
- e.g. adding z-index to card could push it above a sticky header
- Need to isolate z-index change in a stacking context
- One way would be to give the container a z-index (with positioned - relative)
- Better would be
isolation: isolate
instead
- Global ui
- Modals, dropdowns, tooltip, etc... which should go over everything
- Portals in react
- Render component in a different area than the component tree
- e.g. put model after application in DOM
- API is low level, most developers not supposed to use directly - libraries
- Putting model after application in DOM still creates issues
- Can z-order over the top
- isolate the react root
- Recommends the Reach UI library
-
Fixed positioning
-
Similar to absolute but can only be constrained by the viewport, not other positioned elements
-
Ignores scroll position
-
Good for modals
-
Sit in-flow without anchors, but stays stuck on screen when scrolling
-
Incompatibility with some CSS properties
- If an ancestor uses transform it stops being locked to the viewport
- ancestor becomes a containing block, acts like absolute
- same with
filter
andwill-change
- Solutions
- Remove or replace the css property
- Use a portal or some way to move the fixed element to a different container
- Debug snippet
// Replace “.the-fixed-child” for a CSS selector // that matches the fixed-position element: const selector = '.the-fixed-child' function findCulprits(elem) { if (!elem) { throw new Error('Could not find element with that selector') } let parent = elem.parentElement while (parent) { const { transform, willChange, filter } = getComputedStyle(parent) if ( transform !== 'none' || willChange === 'transform' || filter !== 'none' ) { console.warn('🚨 Found a culprit! 🚨\n', parent, { transform, willChange, filter, }) } parent = parent.parentElement } } findCulprits(document.querySelector(selector))
- If an ancestor uses transform it stops being locked to the viewport
-
-
Overflow
- Typically block elements have variable height so they can grow as needed
- If we constrain create an impossible condition - to much content
- Default is to spill outside the bounds without accounting for it in flow calculations
-
visible
-
- Overflow property is shorthand for
overflow-x
andoverflow-y
-
scroll
- Default is to always show scrollbars, except MacOS
-
auto
- Adds scrollbar when required
- Will be a layout shift to shrink content box for scrollbar
-
hidden
- Truncates
- Artistic purposes on decorative elements
- Scroll containers
- Child is always in a scroll container or it isn't
- If one direction is scroll, hidden, auto then visible on the other direction acts like scroll
- Hidden is the same as scroll - but with no scrollbar
- e.g. can be scrolled with tab between interactive elements
-
clip
- Hidden without the scroll container
- If container has border-radius clipping is forced in both directions in certain browsers (chrome)
- Can still tab to hidden interactive elements - but won't scroll
- Horizontal overflow
- Inline elements will wrap
white-space: nowrap;
(withoverflow: auto;
)
- Positioned layout
- Overflow rule will not apply unless positioned element is constrained
- Absolute elements act like static elements in scroll, will be inside scroll vew rather than over border
- Works with rounded bounds
-
Sticky
-
As you scroll changes from being relatively positioned to stuck on an edge of the viewport
-
Will only stick in the parent container, not visible when parent goes out of view
-
Layed out in flow, initial position before scroll remains occupied
-
Troubleshooting
- Setting overflow to hidden, scroll, auto on parent
- Sticks to closest scroll container (rather than viewport), will only stick when scrolling within the scroll container
-
i.e. if you reduce the hight and get a scrollbar
-
- Sticks to closest scroll container (rather than viewport), will only stick when scrolling within the scroll container
-
Script
// Replace “.the-sticky-child” for a CSS selector // that matches the sticky-position element: const selector = '.the-sticky-child' function findCulprits(elem) { if (!elem) { throw new Error('Could not find element with that selector') } let parent = elem.parentElement while (parent) { const { overflow } = getComputedStyle(parent) if (['auto', 'scroll', 'hidden'].includes(overflow)) { console.log(overflow, parent) } parent = parent.parentElement } } findCulprits(document.querySelector(selector))
- Solution
-
Replace hidden with clip
-
auto,scroll: might be able to remove or move lower int he DOM, tricky
-
- Setting overflow to hidden, scroll, auto on parent
- Container isn't big enough
- Sticky element is stretched
- When using flex/grid
- Effectively no space to move in parent
- Thin gap above sticky header
- 1px gap between viewport edge in chrome
- Rounding issue with fractional pixels
- inset element by a pixel
top: -1px;
-
-
Offset
- relative: shifted from natural in-flow position
- absolute: distance from it's containing block's edge
- fixed: based on viewport
- sticky: minimum gap between element and edge of viewport
-
Hidden content
-
display: none;
- effectively removed from DOM
- button cannot be clicked or focused
- Useful with media queries to toggle desktop and mobile variants
- Faster for browser to show or hide then for react to re-reconcile
- React equivalent to media queries don't work well for server side rendering
- Should use display for anything depending on viewport
-
visibility: hidden;
- Can't be seen, still takes space
- If you want to reserve space for an element which will soon be visible
- can be selectively undone by children
- Opacity
- Can be semi-transparent, animated
- Can still interact, focus, select
- Accessibility
- Want to hide text from screen but still there for screen readers
- e.g. Button label when it has an icon
const visuallyHidden = { position: 'absolute', overflow: 'hidden', clip: 'rect(0 0 0 0)', height: '1px', width: '1px', margin: '-1px', padding: 0, border: 0, }
- Can also use
aria-label
- Opposite, want something for visual purpose, but will confuse screen readers
-
aria-hidden="true"
- Won't remove descendants from tab order
inert
attribute tells screen readers to ignore interactive content
-
-
- Aspects
Modern Component Architecture
-
How do we structure Large applications to avoid specificity wars and naming collisions
-
How to tell what style affects what element
-
Component puts walls up around component and you know nothing else will modify it
-
Style component
import styled from 'styles-components' const FormWrapper = styled.form` border: 1px solid; `
- Creates a react component
- When it's rendered styles get a random name to avoid collisions
- Adds style to the head
- Styles are not created until rendered
-
Ecosystem tour
- Vanilla CSS
- No tooling - less complexity, no runtime performance cost
- Modern features like custom properties make some tooling redundant
- Global and unscoped
- Can't easily share data between CSS and JS
- Built for documents, not apps
- Sass / Less
- POwerful tools like for-loops, mixins, nesting
- Requires a build step - slow
- Remains global by nature - not scoped to components
- All build time - can't react to run-time
- Dependency issues
- Aphrodite
- Styles written in JS, used by React components
- Scoping and specificity issues disappear
- Can use JS in CSS
- Adds vendor prefixes
- CS and JSX in same file
- Requires build step
- Larger bundle size, runtime cost
- Styles must be written is JS: property names camelCased, values must be quoted
- Writing global styles requires an extension
- Not very active
- CSS Modules (not a builtin feature, 3rd party project)
- Fixes scoping and specificity
- Like writing straight-up CSS
- No modern convenience features
- Hard to share data between CSS and JS
- SIngle file component (vue, svelte)
- Similar to CSS modules
- styled-components
- Styles are react components
- Solves scoping and specificity
- Just writing CSS
- Requires build system
- For react
- Obfuscates markup tags
- Emotion
- Similar to styled-components
- Can use without react
- Slightly smaller
- Tailwind
- Utilities: short CSS classes which map to specific styles
- Fixes scoping
- Good habits with following a design system - specify sizes instead of units
- built-in design tokens
- Steep learning curve
- Not all CSS can be turned into utilities
- Adds bulk to markup, many classes required - hard to read
- Vanilla CSS
-
styles-components
- Uses a sass-like preprocessor called stylis
- Tagged template literals
- Component names don't have to be globally unique
- picks a unique hash even for components with the same name
styled
object has methods for every HTML tag * Creates a react component representing that tag with the style applied- Alternative writing method - css prop, requires a babel plugin
babel-plugin-styled-components
picks semantically meaningful class names in developmentvscode-styled-components
for VS Code- Has server side rendering support
&
is a reference to the class name that will be created
const TextInput = styled.input` &:focus { outline: 3px auto blue; } `
-
Global styles
- CSS resets
- Baseline styles for native elements
// GlobalStyles.js import { createGlobalStyle } from 'styled-components' const GlobalStyles = createGlobalStyle` *, *::before, *::after { box-sizing: border-box; } html { font-size: 1.125rem; } body { background-color: hsl(0deg 0% 95%); } ` export default GlobalStyles
- When rendered injects all it's css into the
<head>
-
Dynamic styles
- Using style prop means styling is changed in multiple places
- Inline also only have access to a subset of what you can do with css - e.g. can't use :focus
- Template interpolation in styled
const Wrapper = styled.button` color: ${props => props.color}; padding: 16px 24px; `; ... <Wrapper color={'blue'}> ...
-
Can use another style as a base
styled(Base)` ... `
- Can also compose on your own components, but need to pass down
className
as
prop can dynamically change what type of element is rendered- Can pass a component instead of a string
- Component libraries
- Collection of generic, reusable components that can be dropped into multiple applications
- Consistency between projects
- Don't have to build everything from scratch
- Design system
- designer version of the component library
- vector graphics produced in tools like Figma
- Design tokens: scales for sizes or colors, token is a value in that scale
- designer version of the component library
- Specialized, and application specific components always needed
- Doesn't recommend using these, because you need to understand the style and be able to overwrite it
- Good for quick projects, MVPs, hackathons
- ReachUI
- Un-opinionated about design
- Deals with accessability issues
- Single source of styles
- Contextual styles
- Sometimes need the same component to use different styles in different places
- Want links in quotes to be black text without an underline
- Could add an
a { ... }
section in the css forQuoteContent
- Can't see from looking at the style for the link that it can be a different colour
- Can use
${TextLink}
instead which is better because it's more specific- Invert it
const TextLink = styled.a` /* Standard styles: */ color: blue; text-decoration: none; /* Styles when rendered inside a quote: */ ${QuoteContent} & { color: black; text-decoration: revert; } `
Flexbox
- Another layout mode
- Set of things, want to control the distribution of space along a primary axis
- Whether elements
- 1D layouts
display: flex
sets layout of children inside the container, container still flows- Layout inside children is still flow
- Primary axis: along container
- Cross axis: perpendicular to container
-
flex-direction: row;
- primary horizontal
-
flex-direction: column;
- primary vertical
-
-
justify-content
- for primary axis
-
flex-start
-
flex-end
-
center
-
space-between
- equal spacing between elements (no space with ends)
-
space-around
- equal spacing around elements, half space at ends
-
space-evenly
- same spacing between items and border
-
align-items
- for cross axis
-
flex-start
-
flex-end
-
center
-
stretch
-
baseline
- aligns the baseline of all children, fonts of different sizes sit on the same line
- Works with inputs, buttons, etc...
- Safari won't align baseline with an input/button unless it has text in it - fixed by adding a placeholder
-
align-self
- On a child to override alignment (cross axis)
- When you shrink the container there's a point where it gets a scrollbar
- Children have a minimum size - doesn't want to overflow
- Width and height are not hard rules
- Hypothetical dimensions
- Only respected when there's space
- Width/height depend on flex-direction
flex-basis
like child dimension along primary - Can't scale below min size - width can
- growing
flex-grow
is ratio of whitespace that should be allocated to child- overrides
flex-basis
- overrides
- No effect if no empty space
- shrinking
flex-grow
is ratio of negative space that should be subtracted from child when not enough space- Distribute space between minimum size and hypothetical size
- Can't shrink below min size
- Flex will squash images if no space
-
flex-shrink: 0;
-
- Flex shorthand
- 3 values
- grow
- shrink
- basis
-
flex: 1;
flex-grow: 1
,flex-basis: 0
,flex-shrink: 1
(default)- shrinking each child to have a hypothetical width of 0 and distributing space between each child
- Assigning
flex-grow
to the same value on multiple children may not result in them being the same size if the content has different sizes- Evenly distributes the empty space, but one starts larger
- Can set
width: 0px;
to fix - sets hypothetical space to 0, which means they both start the same size - setting
flex-basis
does the same thing
- 3 values
- Constraints
- Want to set limits rather than proportions between elements
min-width
,max-width
,min-height
,max-height
- In a row
flex-basis
acts likewidth
and respects constraints set by min/max width
- Shorthand gotchas
flex: 1;
setsflex-basis
to 0 which overrides width
- Wrapping
- Inline elements in flow can be wrapped over multiple lines
- Can do something similar with flex
- Without wrapping end up with scrollbar when we hit minimum sizes of all elements
- Set
flex-wrap: wrap;
on container - Will wrap instead of shrinking children (i.e. set
flex-basis
) - Bottom line will still expand to fill row
- Set
max-width
- Set
- Content vs items
justify-content
positioning a group of items (all the content)align-items
positioning a single item- Line wrapping
align-items
Each item moves within th context of it's own rowalign-content
Moves lines within the container
- Groups and gaps
- e.g. have a header with a title and two buttons, want to move the buttons over to the right
- Could wrap buttons in a div and use
space-between
- Could use
margin-right: auto;
on the title to fill out space- Suggested by the flexbox authors
- But buttons will be squished together
- On container:
gap: 8px;
adds spacing between children
- Ordering
flex-direction
-row-reverse
,column-reverse
- Swaps
flex-start
andflex-end
- Changing order and axis direction
- Just flip order of children without changing alignment
- Also justify content in the opposite direction
flex-direction: row-reverse; justify-content: flex-end;
- Only changes visual ordering, not keyboard navigation
- Can use this to e.g. put ToC before content first in tab order, but still be on the right
- Other mechanisms
order
property on individual children - similar to z-order, higher order shows up later
- CSS Grid is better for complex ordering
- Flexbox interactions
- Elements can't participate in multiple layout modes at once
- Positioned flex children
- Positioned layout always wins
- Relative position
- A bit of an exception, asking it to move offset from original position
- Inherits the original and applies offset
- Margin collapse
- Exclusive to flow layout
- z-index
- flexbox supports, uses z-index as if it's being rendered with positioned layout
- Combining multiple layouts
- Flex looks at each child to work out how to grow to fit
- Can't use percents, asking parent for height, but parent is asking child
- Exercise
- 2 column layout
- Container is height of first
- Second scrolls
- Second column have a height of 0 so it doesn't affect parent size
- Overflow auto on parent for scroll
- Make the left colum stick to the top of the container so it stays when parent scrolls
Other Notes
- Padding doesn't work in inline elements
- images and
display: block;
, orline-height: 0;
- Remove whitespace around
- Adding
align-items: flex-start;
makes flex put tighter boxes around items? TODO- or
align-self: flex-start;
- or
- Wrap in Side (
flex: 1;
) elements- Sets the hypothetical size to 0 and will consume space evenly
- Flex will still stop it from going below overflow width
- Can get weird aspect ratio stuff on images with flex properties
- Put flex properties on a wrapper and make image
width: 100%;
instead
- Put flex properties on a wrapper and make image