Graduate Program KB

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 86
      a {
        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 chrome
        p {
          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
  • Box model

    • Aspects
      1. Content
      2. Padding
      3. Border
      4. margin
    • Inspector
      • Orange box - margin
      • Yellow box - border
      • Green box - padding
      • Blue box - content
    • Box sizing
      • box-sizing property
      • content-box Only takes inner content into account
      • border-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
        • 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
      • 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
          • 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 not 100%
        • 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
        • 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
        • 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
      • 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, including html, 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

        1. Only vertical margins collapse
        • Can change writing-mode so blocks stack horizontally - flips this rule
        1. Margins only collapse in flow layout
        2. 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
        1. Bigger margin wins, smaller is completely collapsed inside larger
        2. 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
        1. Margins need to touch to collapse
        • Blocked by padding/boarder
        • Blocked by a gap
        • Blocked by a scroll container (overflow)
        1. 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
        1. More than 2 margins can collapse (e.g. adjacent items and their parents)
        2. Negative margins collapse - most negative wins
        3. Positive and negative margins cancel
        4. 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
        1. Constrains certain children
        2. 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
          • 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 and will-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))
          
      • 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 and overflow-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; (with overflow: 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

          • 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

        • 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

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
  • 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 development
    • vscode-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
      • 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 for QuoteContent
        • 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
    • 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
      1. grow
      2. shrink
      3. 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
  • Constraints
    • Want to set limits rather than proportions between elements
    • min-width, max-width, min-height, max-height
    • In a row flex-basis acts like width and respects constraints set by min/max width
  • Shorthand gotchas
    • flex: 1; sets flex-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
    • 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 row
        • align-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 and flex-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;, or line-height: 0;
    • Remove whitespace around
  • Adding align-items: flex-start; makes flex put tighter boxes around items? TODO
    • or align-self: flex-start;
  • 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