Skip to content

Instantly share code, notes, and snippets.

@djibe
Last active November 4, 2024 17:41
Show Gist options
  • Save djibe/2d0543189101ce04c5f38096e5d1449a to your computer and use it in GitHub Desktop.
Save djibe/2d0543189101ce04c5f38096e5d1449a to your computer and use it in GitHub Desktop.
State of CSS 2024 Memo

State of CSS 2024 Memo

Reset CSS

/* 1. Use a more-intuitive box-sizing model */
*, *::before, *::after {
  box-sizing: border-box;
}

/* 2. Remove default margin */
* {
  margin: 0;
}

body {
  /* 3. Add accessible line-height */
  line-height: 1.5;
  /* 4. Improve text rendering */
  -webkit-font-smoothing: antialiased;
}

/* 5. Improve media defaults */
img, picture, video, canvas, svg {
  display: block;
  max-width: 100%;
}

/* 6. Inherit fonts for form controls */
input, button, textarea, select {
  font: inherit;
}

/* 7. Avoid text overflows */
p, h1, h2, h3, h4, h5, h6 {
  overflow-wrap: break-word;
}

/* 8. Improve line wrapping */
p {
  text-wrap: pretty;
}
h1, h2, h3, h4, h5, h6 {
  text-wrap: balance;
}

/*
  9. Create a root stacking context
*/
#root, #__next {
  isolation: isolate;
}

-- Josh Comeau - The CSS Reset

/***
    The new CSS reset - version 1.11.3 (last updated 25.08.2024)
    GitHub page: https://github.com/elad2412/the-new-css-reset
***/

/*
    Remove all the styles of the "User-Agent-Stylesheet", except for the 'display' property
    - The "symbol *" part is to solve Firefox SVG sprite bug
    - The "html" element is excluded, otherwise a bug in Chrome breaks the CSS hyphens property (https://github.com/elad2412/the-new-css-reset/issues/36)
 */
*:where(:not(html, iframe, canvas, img, svg, video, audio):not(svg *, symbol *)) {
    all: unset;
    display: revert;
}

/* Preferred box-sizing value */
*,
*::before,
*::after {
    box-sizing: border-box;
}

/* Fix mobile Safari increase font-size on landscape mode */
html {
    -moz-text-size-adjust: none;
    -webkit-text-size-adjust: none;
    text-size-adjust: none;
}

/* Reapply the pointer cursor for anchor tags */
a, button {
    cursor: revert;
}

/* Remove list styles (bullets/numbers) */
ol, ul, menu, summary {
    list-style: none;
}

/* Firefox: solve issue where nested ordered lists continue numbering from parent (https://bugzilla.mozilla.org/show_bug.cgi?id=1881517) */
ol {
    counter-reset: revert;
}

/* For images to not be able to exceed their container */
img {
    max-inline-size: 100%;
    max-block-size: 100%;
}

/* removes spacing between cells in tables */
table {
    border-collapse: collapse;
}

/* Safari - solving issue when using user-select:none on the <body> text input doesn't working */
input, textarea {
    -webkit-user-select: auto;
}

/* revert the 'white-space' property for textarea elements on Safari */
textarea {
    white-space: revert;
}

/* minimum style to allow to style meter element */
meter {
    -webkit-appearance: revert;
    appearance: revert;
}

/* preformatted text - use only for this feature */
:where(pre) {
    all: revert;
    box-sizing: border-box;
}

/* reset default text opacity of input placeholder */
::placeholder {
    color: unset;
}

/* fix the feature of 'hidden' attribute.
   display:revert; revert to element instead of attribute */
:where([hidden]) {
    display: none;
}

/* revert for bug in Chromium browsers
   - fix for the content editable attribute will work properly.
   - webkit-user-select: auto; added for Safari in case of using user-select:none on wrapper element*/
:where([contenteditable]:not([contenteditable="false"])) {
    -moz-user-modify: read-write;
    -webkit-user-modify: read-write;
    overflow-wrap: break-word;
    -webkit-line-break: after-white-space;
    -webkit-user-select: auto;
}

/* apply back the draggable feature - exist only in Chromium and Safari */
:where([draggable="true"]) {
    -webkit-user-drag: element;
}

/* Revert Modal native behavior */
:where(dialog:modal) {
    all: revert;
    box-sizing: border-box;
}

/* Remove details summary webkit styles */
::-webkit-details-marker {
    display: none;
}

Alternative CSS reset by Andy Bell

/* Box sizing rules */
*,
*::before,
*::after {
  box-sizing: border-box;
}

/* Prevent font size inflation */
html {
  -moz-text-size-adjust: none;
  -webkit-text-size-adjust: none;
  text-size-adjust: none;
}

/* Remove default margin in favour of better control in authored CSS */
body, h1, h2, h3, h4, p,
figure, blockquote, dl, dd {
  margin: 0;
}

/* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */
ul[role='list'],
ol[role='list'] {
  list-style: none;
}

/* Set core body defaults */
body {
  min-height: 100vh;
  line-height: 1.5;
}

/* Set shorter line heights on headings and interactive elements */
h1, h2, h3, h4,
button, input, label {
  line-height: 1.1;
}

/* Balance text wrapping on headings */
h1, h2,
h3, h4 {
  text-wrap: balance;
}

/* A elements that don't have a class get default styles */
a:not([class]) {
  text-decoration-skip-ink: auto;
  color: currentColor;
}

/* Make images easier to work with */
img,
picture {
  max-width: 100%;
  display: block;
}

/* Inherit fonts for inputs and buttons */
input, button,
textarea, select {
  font: inherit;
}

/* Make sure textareas without a rows attribute are not tiny */
textarea:not([rows]) {
  min-height: 10em;
}

/* Anything that has been anchored to should have extra scroll margin */
:target {
  scroll-margin-block: 5ex;
}

Smooth page transitions

@view-transition {
  navigation: auto;
}

Images

Responsive images for background images.

background-image: url("fallback.jpg");
background-image:
  image-set("photo-small.jpg" 1x,
    "photo-large.jpg" 2x,
    "photo-print.jpg" 600dpi);

Layouts

Modern default layout (WIP)

Tutorials

Setup

body {
  display: grid;
  justify-items: center;
  align-content: start;
  min-height: 100vh;
}

Spacing

.item:not(:last-child) {
  margin-right: 1.6rem;
}

or

```css
.item + .item {
  margin-left: 1.6rem;
}

Center element

.parent {
  display: grid;
  place-items: center;
}

or with flexbox

.parent {
  display: flex;
}

.child {
  margin: auto;
}

Definition list inline

Start your definition list as <dl class="dl-inline">

.dl-inline {
  display: grid;
  grid-template-columns: max-content auto;
  grid-gap: 0.5rem 1.5rem;
}
.dl-inline dd {
  padding-left: 0;
  margin: 0;
}
.dl-inline dd + dt {
  margin-top: 0;
}

Modern image gallery

.gallery-container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  grid-auto-rows: 100px;
  grid-gap: 8px;
  grid-auto-flow: dense;
}

Get all elements between 2 with :has

Master :has()

<ul>
  <li>outside</li>
  <li class="upper">upper</li>
  <li>inside</li>
  <li>inside</li>
  <li>inside</li>
  <li>inside</li>
  <li class="lower">lower</li>
  <li>outside</li>
</ul>
.upper ~ :has(~ .lower) {
	outline: 1px solid red;
}

Bramus!

Quantity queries using has() selector

Select .container if it has between 3 and 10 child elements

.container:has(> :nth-last-child(3):nth-child(-n + 8)) {
  /*                */
  /* your CSS here  */
  /*                */
}

CSS Tips


Shapes

Backdrop-filter

Make an element stand out: backdrop-filter

Interactions

Input colors

Style checkbox, radio, range and progress: accent-color: auto;

Animate to width or height: auto (button, details, collapse)

nav a {
    width: 80px;
    overflow-x: clip;
    transition: width 0.35s ease;

    &:hover,
    &:focus-visible {
        width: calc-size(max-content, size); /* πŸ‘ˆ */
    }
}

/* Or a notification */
:root {
    interpolate-size: allow-keywords; /* πŸ‘ˆ */
}

.item {
    height: auto; /* πŸ‘ˆ */

    @starting-style {
        height: 0px;
    }
}

-- Chrome dev

Focus styles

:is(a, button, input, textarea, summary) {
  --outline-size: max(2px, 0.08em);
  --outline-style: solid;
  --outline-color: currentColor;
}

/* Focus: active at click, touch and keyboard nav */
:is(a, button, input, textarea, summary):focus {
  outline: var(--outline-size) var(--outline-style) var(--outline-color);
  outline-offset: var(--outline-offset, var(--outline-size));
}


/* Focus-visible: active at keyboard nav */
:is(a, button, input, textarea, summary):focus-visible {
  outline: var(--outline-size) var(--outline-style) var(--outline-color); /* or none*/
  outline-offset: var(--outline-offset, var(--outline-size));
}

:is(a, button, input, textarea, summary):focus:not(:focus-visible) {
  outline: none;
}

/* :focus:not(:focus-visible): active at click and touch */

Stephanie Eckles

Old CSS versus New CSS

Style groups

a:hover,
a:focus {
  /* Style */
}

a:is(:hover, :focus){
  /* Style */
}

Centering

margin-left: auto;
margin-right: auto;

// Now
margin-inline: auto;

Hover effect

.card:has(:hover, :focus){
  /* Style */
}

Line length

article {
  width: min(100%, 80ch);
}

article:is(h1, h2, h3, h4, h5, h6) {
  text-wrap: balance;
}

Color palette

/* Easy to maintain! */
:root {
  --primary-color: #000;
  --gray-dark: color-mix(in srgb, var(--primary-color), #fff 25%);
  --gray-medium: color-mix(in srgb, var(--primary-color), #fff 40%);
  --gray-light: color-mix(in srgb, var(--primary-color), #fff 60%);
  --gray-lighter: color-mix(in srgb, var(--primary-color), #fff 75%);
}

Read more on SmashingMagazine


Type CSS variables

Benefit: ,Easy to debug using Dev tools, implicit data validation, can be animated if the type allows it, available globally with a default value.

/*
  Typed CSS variables! 🀩
  Easy to debug and the browser will help you πŸ˜ƒ
*/
@property --color {
  syntax: '<color>';
  inherits: true;
  initial-value: #586de7; 
}
@property --size {
  syntax: '<length>';
  inherits: true;
  initial-value: 20px; 
}
@property --cols {
  syntax: '<integer>';
  inherits: true;
  initial-value: 12; 
}

CSS Tip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment