Opinionated CSS Defaults

work in progress

Prompted by Declan Chidlow’s My Opinionated CSS Reset, which in turn made me revisit Andy Bell’s A (more) Modern CSS Reset, Manuel Matuzović’s uaplus.css and others.

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

Despite some folks being critical, I still think this is a decent default.

:root {
    /* modular scale-ish; cf. https://www.modularscale.com/?1.5 */
    --spacing: 0.5rem;
    --spacing-sm1: calc(var(--spacing) * 0.667);
    --spacing-sm2: calc(var(--spacing) * 0.444);
    --spacing-sm3: calc(var(--spacing) * 0.296);
    --spacing-lg1: calc(var(--spacing) * 1.5);
    --spacing-lg2: calc(var(--spacing) * 2.25);
    --spacing-lg3: calc(var(--spacing) * 3.375);

    --animation-duration: 200ms;
}

There’s no particular reason to use :root over html for custom properties; it’s just a habit.

img {
    display: block;
    max-width: 100%;
    height: auto;
}
button,
summary {
    cursor: pointer;
}
textarea:not([rows]) {
    min-height: 8lh;
}

Typography

body {
    font-family: system-ui, sans-serif;
    line-height: 1.5;
    /* prevent font-size inflation; cf.
       https://kilianvalkhof.com/2022/css-html/your-css-reset-needs-text-size-adjust-probably/ */
    -moz-text-size-adjust: none;
    -webkit-text-size-adjust: none;
    text-size-adjust: none;
    /* disable macOS's default subpixel antialiasing for consistency across
       platforms; cf. https://dbushell.com/2024/11/05/webkit-font-smoothing/ */
    -webkit-font-smoothing: antialiased;
}

We want form elements to assume the respective base font:

input,
textarea,
select,
button {
    font-family: inherit;
    font-size: inherit;
}
a {
    text-underline-offset: 0.15lh; /* XXX: magic value */

    @media (prefers-reduced-motion: no-preference) {
        transition-property: text-underline-offset, text-decoration-color;
        transition-duration: var(--animation-duration);
    }

    &:not(:focus, :hover, :active) {
        text-underline-offset: 0.1lh; /* XXX: magic value */
        /* XXX: a11y might be impacted by insufficient color contrast */
        text-decoration-color: color-mix(in srgb, currentColor, transparent 50%);
    }
}

Utilities

.nonvisual:not(:focus, :active) {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    white-space: nowrap;
    clip-path: inset(50%);
}
.stack > * {
    margin-block: 0;

    & + * {
        margin-block-start: var(--spacing);
    }
}