-
Before reaching for a class to target an element, first try to accomplish that with combinators, or descendant selectors.
-
List of inheritable properties: https://www.sitepoint.com/css-inheritance-introduction#list-css-properties-inherit
*,
*:before,
*:after {
box-sizing: border-box;
}
-
When 3 values are provided for padding/margin/border, it takes the provided value for 'right' and plugs that into left.
-
When border color isn't specified, it inherits the font-color for that element. This can be explicitly stated using the
currentColor
keyword for the color arg in statements. -
outline-offset
allows you to add a gap between the element and the outline, like a second border.
-
Margin collapse is when overlapping margins take up less space than their total sums.
-
Only vertical margins collapse: however, this will flip if the
writing-mode
is switched. The most accurate way to view this is that only block-direction margins collapse. -
Only adjacent elements collapse: placing an
hr
between two elements, for example, would be enough to prevent this from happening. -
The largest margin will win out in a collapse, and dictate the space taken up.
-
Nesting one of the elements in a container like a
div
will NOT prevent collapsing. For this to happen, there can be no elements in-between the parent and child, no height set on the parent, and no border or padding set on the relevant parent edge. -
Margins can collapse in the same direction, as with a parent and child.
-
Negative margins can still collapse; In the case of positive and negative margins overlapping, they'll be added together, and that sum will be the computed margin.
For multiple (more than 2) overlapping margins of mixed positivity:
- Find the largest positive margin
- Find the largest negative margin
- Add them together
"Margin is like putting glue on something before you’ve decided what to stick it to, or if it should be stuck to anything."
- Margin collapse doesn't work in Flexbox or Grid layouts.
-
calc()
is helpful for combining values, and presenting the math behind values, making them easier to reason about. -
Instead of reaching for a px to rem calculator, we can do the math ourselves using
calc()
:
h2 {
font-size: calc(24 / 16 * 1rem);
}
- The auto margin technique for centering elements is still quite useful when you have a single element that you need centered, and making the parent element a Flexbox or Grid container would be overkill.
- When there is a conflict between layout modes, positioned layout always wins
-
Inline elements don't have a width or height.
-
Inline elements have extra "magic space" because the browser regards them as typography. To fix this quirk with images, either set their display as
block
or set theline-height
on the wrapping div to0
- By default, block-level elements have dynamic sizing.
-
Be aware of, but don't worry too much about space sensitivity
-
Disadvantages: Inline block doesn't line-wrap
-
Replaced elements (like img, video, or canvas tags) embed a foreign object. They mostly behave as inline elements, but they can affect block layout in some ways.
-
Buttons behave almost, but not exactly, as replaced elements.
To normalize application height when trying to fill the viewport:
- Put
height: 100%
on every element before your main one. - Put
min-height: 100%
on that wrapper, and don't try using percentage-based heights there.
vh
units are unfortunately not a viable solution here, since they're based on the total possible height after taking scrolling into consideration on mobile devices.
-
Width can be expressed either as a keyword that dictates it's behavior (like
auto
), or as a measurement likepercentage
orpx
. -
min-content
lets us shrink the element as much as it's children will allow. -
max-content
is the opposite of the above, with no line-breaks whatsoever. This is perfect for situations like only wanting background-color immediately around the child text. -
the
fit-content
rule lets block level elements fill available space. It's a happy medium between the above two rules.
-
Padding gotcha: when it comes to padding, percentages always refer to the element's width, even for the top and bottom.
-
If a parent or grandparent of an
position: fixed
element usestransform
, that will become the containing block for the fixed element, making it absolutely positioned. Transformed parents can't have fixed children. The same goes forwill-change: transform
-
When using the
flex
shorthand, theflex-basis
value will be set to 0, which will override any width you set. It's best to always explicitly set that value to whatever you need it to bo. -
vw
DOES NOT count the scrollbar in it's calculation!
- When it comes to grid alignment:
"justify-content applies to the grid structure, changing the columns. justify-items applies to the child elements, without affecting the shape of the grid."
-
When using
minmax()
to set variable grid dimensions, the flexible unit must be LAST:minmax(250px, 1fr)
-
To add colored dividers to a grid layout, you need to remove the gap and add padding, and then carefully add in borders.
-
Be careful with
fr
, as it can lead to overflow issues (which can be circumvented by usingminmax
or similar techniques to set a minimum width).
-
Hiding content via
display: none
or not rendering in React? These options have minute performance tradeoffs (speed vs memory), but either one is generally fine. -
visibility: hidden
is the preferred technique for hiding an element when you want it to be invisible, but still take up space. -
Another interesting thing about this property is that it can be selectively undone by children.
-
Use opacity for fading in and out, or partial visibility, not hiding.
-
Images have an intrinsic size, namely the dimensions of the original file.
-
They also have an intrinsic aspect ratio, meaning that if we only provide a value for
width
orheight
, the other will scale to preserve that ratio. -
object-fit
contains several ways to style replaced elements like images. -
You can also toggle how a replaced element is aligned using
object-position
-
The default align-items for a cross-axis in flexbox is stretch, which can lead to odd image behavior.
-
Wrapping images in (non-flex) containers sidesteps quite a few issues with flexbox
- The
srcset
attribute lets you determine several different image sizes, and the browser decides the correct one.
- the
:hover
event doesn't exist on mobile devices. To set hover styling:
@media (hover: hover) and (pointer: fine) {
button:hover {
text-decoration: underline;
}
}
- A newer query type is preference-based. This is most useful for a11y concerns:
@media (prefers-reduced-motion: no-preference) {
/* Animations here */
}
- Strongly consider utilizing buffers in your breakpoints to account for padding, etc, on the individual element level
Common breakpoints:
0-550px — Mobile 550-1100px — Tablet 1100-1500px — Laptop 1500+px — Desktop
- Josh's recommended solution, using styled-components:
// For this example, I'm going mobile-first.
// constants.js
const BREAKPOINTS = {
tabletMin: 550,
laptopMin: 1100,
desktopMin: 1500,
}
const QUERIES = {
'tabletAndUp': `(min-width: ${BREAKPOINTS.tabletMin / 16}rem)`
'laptopAndUp': `(min-width: ${BREAKPOINTS.laptopMin / 16}rem)`
'desktopAndUp': `(min-width: ${BREAKPOINTS.desktopMin / 16}rem)`
}
- Note the use of rems as the breakpoint unit above.
-
Add
outline: none
to an element; this breaks keyboard a11y -
Negative
z-index
values create more problems than they solve. -
Don't build your own modals.
-
For when content needs to scroll, favor setting overflow to
auto
instead ofscroll
, keeping in mind that if you know for certain that a container needs to scroll, settingoverflow-y: scroll
may make for smoother behavior. -
overflow: hidden
is a strong option for obscuring decoration without needing to deal with scrollbars. -
ALWAYS comment the above property when you use it, because it's too easy to break something by refactoring it out.
-
white-space: nowrap
is a good way to deal with horizontal scrolling.
-
Every element has this as a default
position
-
Setting position to any value other than
static
grants us access to thetop
,left
,right
, andbottom
properties.
-
This sort of positioning pulls an element completely out of flow.
-
A drawback of this strategy is that it can collapse parent elements.
-
Josh says:
"When you place an absolute item without specifying top/left/right/bottom, it sits where it would otherwise sit in its in-flow position, but it's incorporeal, it doesn't take up any space."
-
Only non-static elements can constrain absolutely-positioned children.
The system for containing absolutely positioned elements is like so:
-
The DOM tree is traversed back to the top, looking for the first non-static parent, If found, the absolute child will be anchored to that element.
-
If none exist, it'll be anchored to the "initial containing block", a box the size of the viewport at the top of the document.
- This property makes elements relative to their natural position
- Constrains certain children
- Enables additional CSS properties
-
Relatively positioned elements can overlap static siblings without z-index (if they're styled in a manner to allow that overlap), because the browser paints static elements first, even if they're declared later in the rendering order.
-
We need to do two things to make sure one sibling is absolutely positioned over another:
- Make sure that element's position isn't
static
- Give that element a larger z-index than that of it's sibling.
-
Deliberate positioning of siblings is the first technique to consider when stacking elements to forgo the need for
z-index
, AND maintain the DOM order. -
The
isolation
property creates a new stacking context: this is a compelling technique for when you need more complicated stacking logic than the above technique can provide, also precluding the need for z-index. -
Stacking Context is how we determine precisely which elements can be elevated over another element. Some ways we can create a new stacking context:
-
Setting opacity to less than 1
-
Setting a position to fixed or sticky.
-
Applying a
mix-blend-mode
to anything other than normal. -
Adding
z-index
to aflex
orgrid
child. -
Using transform, filter, clip-path, or perspective
-
Explicitly creating a context with
isolation: isolate
-
Grid children can take advantage of z-index without the need to adjust their
position
type.
-
-
Sticky positioned elements will scroll within their parent container, but if that parent scrolls off the screen, the sticky element will too.
-
If
position: sticky
isn't working, go through these troubleshooting steps:- Make sure a parent isn't hiding
overflow
- Make sure the container is big enough to allow the sticky behavior you expect.
- Is Flexbox or Grid stretching the element?
- Make sure a parent isn't hiding
color: inherit
is a good way to style color in a more maintainable way than hard-coding the color.
To center using absolute positioning:
position: absolute
- All 4 cardinal directions (top, left, bottom, right) set to
0px
margin: auto
- An explicit width and height
- When you have a single element that needs to break from the usual flow of it's sibling elements, consider using a wrapping container to impose the behavior you need in that particular instance.
- The
ch
unit is roughly equivalent to a0
, and will vary depending on the particular font.
-
Favor
rem
s for typography for body text,vw
s for headings where great amounts of flexibility are needed. -
clamp()
can be useful for the above, as Josh demonstrates:
font-size: clamp(
1.5rem,
4vw + 1rem,
3rem
);
-
Pixels for box model properties
-
Go with either pixels or percentages for width or height, depending on the needs of your application.
-
Prefer hsl for colors.
-
Use
em
ONLY when you need a property to scale directly with font-size.
-
CSS variables are inheritable, but are not globally scoped.
-
Variables take an optional second argument, which is a default or fallback value.
-
CSS variables can be declared as fragments and composed, in the case of properties that take multiple parameters like
border
, orcolor
s using HSL.