{"id":7245,"date":"2025-09-24T13:18:49","date_gmt":"2025-09-24T18:18:49","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=7245"},"modified":"2025-10-10T16:49:15","modified_gmt":"2025-10-10T21:49:15","slug":"the-coyier-css-starter","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/the-coyier-css-starter\/","title":{"rendered":"The Coyier CSS Starter"},"content":{"rendered":"\n<p>I felt called out by Mike Mai&#8217;s <em><a href=\"https:\/\/mikemai.net\/blog\/2024\/11\/01\/you-are-not-a-css-dev-if-you-have-not-made-a-css-reset.html\">You are not a CSS dev if you have not made a CSS reset<\/a>.<\/em><\/p>\n\n\n\n<p>I hadn&#8217;t! I mean, I&#8217;ve used <code>* { box-sizing: border-box; }<\/code> a ton and, way back, I used to use that same universal selector to wipe away margins and padding, which was the inspiration behind the <a href=\"https:\/\/css-tricks.com\/\">CSS-Tricks<\/a> logo, believe it or not. <\/p>\n\n\n\n<p>But I never made or published anything and planted a stake in the ground and said <em>&#8220;This one. This one is mine.&#8221;<\/em><\/p>\n\n\n\n<p>So I&#8217;m going to do that. <\/p>\n\n\n\n<p>First, I think it&#8217;s important to lay some ground rules. Some principles, really. There are a lot of directions a thing like this can go, and without what it&#8217;s for (and not for) it&#8217;s fairly useless.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Principles<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>This is for me.<\/strong> The styles in here are useful to me. They are things I find myself doing very often (or forgetting to do.) I&#8217;d like to be using this in <em>most<\/em> demos I make and dipping into it for any future project. I do hope y&#8217;all will find some value in it too of course, hence blogging about it, but as a guiding principal it&#8217;s for me.<\/li>\n\n\n\n<li><strong>This is not a <em>reset<\/em>, it&#8217;s an opinionated <em>starter<\/em>.<\/strong> I&#8217;m not trying to wipe out <em>all<\/em> existing styles from user-agent stylesheets. I wipe out the ones that are useful for me to remove. It&#8217;s more about <em>adding<\/em> useful styles, <em>improving<\/em> UX broadly, and <em>fixing<\/em> common issues.<\/li>\n\n\n\n<li><strong>Use only logical properties.<\/strong> It&#8217;s a <a href=\"https:\/\/frontendmasters.com\/blog\/should-we-never-use-non-logical-properties\/\">net gain<\/a>.<\/li>\n\n\n\n<li><strong>Don&#8217;t use <code>--custom-properties<\/code>.<\/strong> Setting those up is a step too far for this starter. Use <a href=\"https:\/\/open-props.style\/\">Open Props<\/a> for that sort of thing.<\/li>\n\n\n\n<li><strong>Use <code>@layer<\/code><\/strong> <a href=\"https:\/\/mayank.co\/blog\/css-reset-layer\/\">because<\/a> &#8220;you\u2019ll need to do it anyway if you ever want to use layers anywhere else.&#8221;<\/li>\n\n\n\n<li><strong>Do accessibility things that are easy to forget about<\/strong>, but nothing so niche it doesn&#8217;t come up for me often\/ever.<\/li>\n\n\n\n<li><strong>Don&#8217;t do too much.<\/strong> None of this is strictly necessary so if it feels too weighty I&#8217;d probably find myself not using it. This whole thing is pointless if I don&#8217;t use it. <a href=\"https:\/\/snook.ca\/archives\/html_and_css\/still-no-css-reset\">Doing nothing<\/a> is totally an option, so if this doesn&#8217;t feel more useful than just <a href=\"https:\/\/aaadaaam.com\/notes\/useful-defaults\/\">defining styles as you go<\/a>, it&#8217;s a fail.<\/li>\n\n\n\n<li><strong>This isn&#8217;t a thing anybody is going to <code>npm install<\/code><\/strong>. It&#8217;s not versioned nor meant to be <em>always<\/em> used wholesale. Copying out useful bits is fine usage.<\/li>\n\n\n\n<li><strong>This is a list of things I <em>almost<\/em> wish were the browser defaults<\/strong> (i.e. in the user agent stylesheet) if I ruled the world and didn&#8217;t have to care about backwards compatibility.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">The Whole Thing<\/h2>\n\n\n\n<p>You can see it <a href=\"https:\/\/codepen.io\/editor\/chriscoyier\/pen\/0198772a-a759-7dc4-b8fc-1dfdbed39fdb\">on this Pen<\/a>, or <a href=\"https:\/\/0198772a-a759-7dc4-b8fc-1dfdbed39fdb.codepenusercontent.com\/style.css\">directly as a file here<\/a>. <\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@layer<\/span> reset {\n  <span class=\"hljs-selector-tag\">html<\/span> {\n    <span class=\"hljs-attribute\">color-scheme<\/span>: light dark;\n    <span class=\"hljs-attribute\">font<\/span>:\n      <span class=\"hljs-built_in\">clamp<\/span>(<span class=\"hljs-number\">1rem<\/span>, <span class=\"hljs-number\">1rem<\/span> + <span class=\"hljs-number\">0.5vw<\/span>, <span class=\"hljs-number\">2rem<\/span>) \/ <span class=\"hljs-number\">1.4<\/span> system-ui,\n      sans-serif;\n    <span class=\"hljs-attribute\">tab-size<\/span>: <span class=\"hljs-number\">2<\/span>;\n    <span class=\"hljs-attribute\">hanging-punctuation<\/span>: first allow-end last;\n    <span class=\"hljs-attribute\">word-break<\/span>: break-word;\n  }\n\n  <span class=\"hljs-selector-tag\">body<\/span> {\n    <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">2rem<\/span>;\n    @media (width &lt; 500px) {\n      <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">1rem<\/span>;\n    }\n  }\n\n  *,\n  *<span class=\"hljs-selector-pseudo\">::before<\/span>,\n  *<span class=\"hljs-selector-pseudo\">::after<\/span> {\n    <span class=\"hljs-attribute\">box-sizing<\/span>: border-box;\n  }\n\n  <span class=\"hljs-selector-tag\">h1<\/span>,\n  <span class=\"hljs-selector-tag\">h2<\/span> {\n    <span class=\"hljs-attribute\">font-weight<\/span>: <span class=\"hljs-number\">900<\/span>;\n    <span class=\"hljs-attribute\">letter-spacing<\/span>: -<span class=\"hljs-number\">0.02rem<\/span>;\n  }\n  <span class=\"hljs-selector-tag\">h1<\/span>,\n  <span class=\"hljs-selector-tag\">h2<\/span>,\n  <span class=\"hljs-selector-tag\">h3<\/span> {\n    <span class=\"hljs-attribute\">line-height<\/span>: <span class=\"hljs-number\">1.1<\/span>;\n  }\n  <span class=\"hljs-selector-tag\">h1<\/span>,\n  <span class=\"hljs-selector-tag\">h2<\/span>,\n  <span class=\"hljs-selector-tag\">h3<\/span>,\n  <span class=\"hljs-selector-tag\">h4<\/span>,\n  <span class=\"hljs-selector-tag\">h5<\/span>,\n  <span class=\"hljs-selector-tag\">h6<\/span> <span class=\"hljs-comment\">\/* FUTURE :heading *\/<\/span> {\n    <span class=\"hljs-attribute\">text-wrap<\/span>: balance;\n    <span class=\"hljs-attribute\">margin-block-start<\/span>: <span class=\"hljs-number\">0<\/span>;\n  }\n\n  <span class=\"hljs-selector-tag\">p<\/span>,\n  <span class=\"hljs-selector-tag\">li<\/span>,\n  <span class=\"hljs-selector-tag\">dd<\/span> {\n    <span class=\"hljs-attribute\">text-wrap<\/span>: pretty;\n    <span class=\"hljs-attribute\">max-inline-size<\/span>: <span class=\"hljs-number\">88ch<\/span>;\n  }\n\n  <span class=\"hljs-selector-tag\">a<\/span> {\n    <span class=\"hljs-attribute\">color<\/span>: <span class=\"hljs-built_in\">oklch<\/span>(<span class=\"hljs-number\">0.68<\/span> <span class=\"hljs-number\">0.17<\/span> <span class=\"hljs-number\">228<\/span>);\n    <span class=\"hljs-attribute\">text-underline-offset<\/span>: <span class=\"hljs-number\">2px<\/span>;\n    &amp;:not(:is(:hover, :focus)) {\n      <span class=\"hljs-attribute\">text-decoration-color<\/span>: <span class=\"hljs-built_in\">color-mix<\/span>(in srgb, currentColor, transparent <span class=\"hljs-number\">50%<\/span>);\n    }\n  }\n\n  <span class=\"hljs-selector-tag\">sub<\/span>,\n  <span class=\"hljs-selector-tag\">sup<\/span> {\n    <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">75%<\/span>;\n    <span class=\"hljs-attribute\">line-height<\/span>: <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-attribute\">position<\/span>: relative;\n    <span class=\"hljs-attribute\">vertical-align<\/span>: baseline;\n  }\n  <span class=\"hljs-selector-tag\">sub<\/span> {\n    <span class=\"hljs-attribute\">inset-block-end<\/span>: -<span class=\"hljs-number\">0.25em<\/span>;\n  }\n  <span class=\"hljs-selector-tag\">sup<\/span> {\n    <span class=\"hljs-attribute\">inset-block-start<\/span>: -<span class=\"hljs-number\">0.5em<\/span>;\n  }\n\n  <span class=\"hljs-selector-tag\">ul<\/span>,\n  <span class=\"hljs-selector-tag\">ol<\/span>,\n  <span class=\"hljs-selector-tag\">dl<\/span> {\n    <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-attribute\">list-style-position<\/span>: inside;\n    ul,\n    ol,\n    dl {\n      <span class=\"hljs-attribute\">padding-inline-start<\/span>: <span class=\"hljs-number\">2ch<\/span>;\n    }\n  }\n\n  <span class=\"hljs-selector-tag\">img<\/span>,\n  <span class=\"hljs-selector-tag\">video<\/span>,\n  <span class=\"hljs-selector-tag\">iframe<\/span> {\n    <span class=\"hljs-attribute\">display<\/span>: block;\n    <span class=\"hljs-attribute\">max-inline-size<\/span>: <span class=\"hljs-number\">100%<\/span>;\n    <span class=\"hljs-attribute\">block-size<\/span>: auto;\n    <span class=\"hljs-attribute\">border-style<\/span>: none;\n  }\n\n  <span class=\"hljs-selector-tag\">figure<\/span> {\n    <span class=\"hljs-attribute\">inline-size<\/span>: fit-content;\n    <span class=\"hljs-attribute\">margin-inline<\/span>: auto;\n  }\n  <span class=\"hljs-selector-tag\">figcaption<\/span> {\n    <span class=\"hljs-attribute\">contain<\/span>: inline-size;\n    <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">90%<\/span>;\n  }\n\n  <span class=\"hljs-selector-tag\">input<\/span>,\n  <span class=\"hljs-selector-tag\">select<\/span>,\n  <span class=\"hljs-selector-tag\">textarea<\/span>,\n  <span class=\"hljs-selector-tag\">button<\/span> {\n    <span class=\"hljs-attribute\">font<\/span>: inherit;\n    <span class=\"hljs-comment\">\/* FUTURE: appearance: base; *\/<\/span>\n  }\n  <span class=\"hljs-selector-tag\">label<\/span> {\n    <span class=\"hljs-attribute\">display<\/span>: block;\n  }\n  <span class=\"hljs-selector-tag\">input<\/span><span class=\"hljs-selector-pseudo\">:not(<\/span>\n    <span class=\"hljs-selector-pseudo\">:where(<\/span>\n      <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"submit\"<\/span>]<\/span>,\n      <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"checkbox\"<\/span>]<\/span>,\n      <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"radio\"<\/span>]<\/span>,\n      <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"button\"<\/span>]<\/span>,\n      <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"reset\"<\/span>]<\/span>\n    )\n  ) {\n    <span class=\"hljs-attribute\">inline-size<\/span>: <span class=\"hljs-number\">100%<\/span>;\n  }\n  <span class=\"hljs-selector-tag\">button<\/span>,\n  <span class=\"hljs-selector-tag\">input<\/span><span class=\"hljs-selector-pseudo\">:where(<\/span>\n    <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"submit\"<\/span>]<\/span>,\n    <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"reset\"<\/span>]<\/span>,\n    <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"button\"<\/span>]<\/span>\n  ) {\n    <span class=\"hljs-attribute\">background<\/span>: CanvasText;\n    <span class=\"hljs-attribute\">color<\/span>: Canvas;\n    <span class=\"hljs-attribute\">border<\/span>: <span class=\"hljs-number\">1px<\/span> solid transparent;\n  }\n  <span class=\"hljs-selector-tag\">textarea<\/span> {\n    <span class=\"hljs-attribute\">field-sizing<\/span>: content;\n    <span class=\"hljs-attribute\">min-block-size<\/span>: <span class=\"hljs-number\">5<\/span>lh;\n    <span class=\"hljs-attribute\">inline-size<\/span>: <span class=\"hljs-number\">100%<\/span>;\n    <span class=\"hljs-attribute\">max-inline-size<\/span>: <span class=\"hljs-number\">100%<\/span>;\n  }\n\n  <span class=\"hljs-selector-tag\">pre<\/span>,\n  <span class=\"hljs-selector-tag\">code<\/span>,\n  <span class=\"hljs-selector-tag\">kbd<\/span>,\n  <span class=\"hljs-selector-tag\">samp<\/span> {\n    <span class=\"hljs-attribute\">font-family<\/span>: ui-monospace, SFMono-Regular, monospace;\n  }\n\n  <span class=\"hljs-selector-tag\">svg<\/span> {\n    <span class=\"hljs-attribute\">fill<\/span>: currentColor;\n  }\n\n  <span class=\"hljs-selector-attr\">&#91;aria-disabled=<span class=\"hljs-string\">\"true\"<\/span> i]<\/span>,\n  <span class=\"hljs-selector-attr\">&#91;disabled]<\/span> {\n    <span class=\"hljs-attribute\">cursor<\/span>: not-allowed;\n  }\n  <span class=\"hljs-selector-attr\">&#91;hidden]<\/span> {\n    <span class=\"hljs-attribute\">display<\/span>: none <span class=\"hljs-meta\">!important<\/span>;\n  }\n  <span class=\"hljs-selector-attr\">&#91;disabled]<\/span>,\n  <span class=\"hljs-selector-tag\">label<\/span><span class=\"hljs-selector-pseudo\">:has(input<\/span><span class=\"hljs-selector-attr\">&#91;disabled]<\/span>) {\n    <span class=\"hljs-attribute\">opacity<\/span>: <span class=\"hljs-number\">0.5<\/span>;\n\n    &#91;disabled] {\n      <span class=\"hljs-attribute\">opacity<\/span>: <span class=\"hljs-number\">1<\/span>;\n    }\n  }\n\n  <span class=\"hljs-selector-tag\">pre<\/span> {\n    <span class=\"hljs-attribute\">white-space<\/span>: pre-wrap;\n    <span class=\"hljs-attribute\">background<\/span>: CanvasText;\n    <span class=\"hljs-attribute\">color<\/span>: Canvas;\n    <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">1.5rem<\/span>;\n  }\n\n  <span class=\"hljs-selector-tag\">hr<\/span> {\n    <span class=\"hljs-attribute\">border-style<\/span>: solid;\n    <span class=\"hljs-attribute\">border-width<\/span>: <span class=\"hljs-number\">1px<\/span> <span class=\"hljs-number\">0<\/span> <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-attribute\">color<\/span>: inherit;\n    <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">0<\/span>;\n    <span class=\"hljs-attribute\">overflow<\/span>: visible;\n    <span class=\"hljs-attribute\">margin-block<\/span>: <span class=\"hljs-number\">2.5rem<\/span>;\n  }\n\n  <span class=\"hljs-selector-pseudo\">:target<\/span> {\n    <span class=\"hljs-attribute\">scroll-margin<\/span>: <span class=\"hljs-number\">3<\/span>rlh;\n  }\n\n  <span class=\"hljs-selector-tag\">table<\/span> {\n    <span class=\"hljs-attribute\">caption-side<\/span>: bottom;\n    <span class=\"hljs-attribute\">border-collapse<\/span>: collapse;\n    td {\n      <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">90%<\/span>;\n    }\n    <span class=\"hljs-selector-tag\">td<\/span>,\n    <span class=\"hljs-selector-tag\">th<\/span> {\n      <span class=\"hljs-attribute\">word-break<\/span>: normal;\n      <span class=\"hljs-attribute\">border<\/span>: <span class=\"hljs-number\">1px<\/span> solid gray;\n      <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">0.5rem<\/span>;\n    }\n  }\n  <span class=\"hljs-selector-attr\">&#91;role=<span class=\"hljs-string\">\"region\"<\/span>]<\/span><span class=\"hljs-selector-attr\">&#91;aria-labelledby]<\/span><span class=\"hljs-selector-attr\">&#91;tabindex]<\/span> {\n    <span class=\"hljs-attribute\">overflow<\/span>: auto;\n  }\n  <span class=\"hljs-selector-tag\">caption<\/span> {\n    <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">90%<\/span>;\n  }\n\n  <span class=\"hljs-selector-class\">.screenreader-only<\/span><span class=\"hljs-selector-pseudo\">:not(<\/span><span class=\"hljs-selector-pseudo\">:focus)<\/span><span class=\"hljs-selector-pseudo\">:not(<\/span><span class=\"hljs-selector-pseudo\">:active)<\/span> {\n    <span class=\"hljs-attribute\">clip<\/span>: <span class=\"hljs-built_in\">rect<\/span>(<span class=\"hljs-number\">0<\/span> <span class=\"hljs-number\">0<\/span> <span class=\"hljs-number\">0<\/span> <span class=\"hljs-number\">0<\/span>);\n    <span class=\"hljs-attribute\">clip-path<\/span>: <span class=\"hljs-built_in\">inset<\/span>(<span class=\"hljs-number\">50%<\/span>);\n    <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">1px<\/span>;\n    <span class=\"hljs-attribute\">overflow<\/span>: hidden;\n    <span class=\"hljs-attribute\">position<\/span>: absolute;\n    <span class=\"hljs-attribute\">white-space<\/span>: nowrap;\n    <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">1px<\/span>;\n  }\n  <span class=\"hljs-selector-pseudo\">:focus-visible<\/span> {\n    <span class=\"hljs-attribute\">outline-offset<\/span>: <span class=\"hljs-number\">2px<\/span>;\n  }\n\n  <span class=\"hljs-keyword\">@media<\/span> (<span class=\"hljs-attribute\">prefers-reduced-motion:<\/span> no-preference) {\n    <span class=\"hljs-keyword\">@view-transition<\/span> {\n      <span class=\"hljs-selector-tag\">navigation<\/span>: <span class=\"hljs-selector-tag\">auto<\/span>;\n    }\n    \n    <span class=\"hljs-selector-tag\">html<\/span> {\n      <span class=\"hljs-attribute\">interpolate-size<\/span>: allow-keywords;\n      &amp;:focus-within {\n        <span class=\"hljs-attribute\">scroll-behavior<\/span>: smooth;\n      }\n    }\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Notes about the Choices<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Layering<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@layer<\/span> reset {\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>There is no usage of <code>:where()<\/code> in here <em>just<\/em> to lower specificity. The usage of <code>:where()<\/code> is only to write selectors that are less repetitive and easier to read. Specificity is already bottomed out due to the <code>@layer<\/code>, and people who choose to use this can position the layer where they want to. <\/p>\n\n\n\n<p>I was convinved this was a good idea from Mayank&#8217;s <a href=\"https:\/\/mayank.co\/blog\/css-reset-layer\/\">Your CSS reset should be layered.<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Color Scheme<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">html<\/span> {\n  <span class=\"hljs-attribute\">color-scheme<\/span>: light dark;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Putting <code>color-scheme: light dark;<\/code> in there is a relatively big choice, because it opts you into needing to deal with both themes for nearly all color\/background-color usage. But that&#8217;s good. People like it when at least their operating system choice is honored. Just this basic thing alone buys dark-mode scrollbars and checkboxes and inputs and stuff, so it&#8217;s worth doing. Now <code>light-dark()<\/code> will work so implementing scheme-specific colors isn&#8217;t so bad.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Clamped Root Font Size<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">html<\/span> {\n  <span class=\"hljs-attribute\">font<\/span>: <span class=\"hljs-built_in\">clamp<\/span>(<span class=\"hljs-number\">1rem<\/span>, <span class=\"hljs-number\">1rem<\/span> + <span class=\"hljs-number\">0.5<\/span>dvw, <span class=\"hljs-number\">2rem<\/span>) \/ <span class=\"hljs-number\">1.4<\/span> system-ui, sans-serif;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Controversial?! Maybe. But because <code>clamp(1rem, 1rem + 0.5dvw, 2rem)<\/code> involves relative units, it should still scale properly with users adjusting their base font size. I feel like setting a fluid font size here (and nowhere else) percolates pretty nicely throughout the document and feels like visually.<\/p>\n\n\n\n<p>That&#8217;s a juiced up <code>line-height<\/code> and <code>system-ui<\/code> as the font which tends to look nice everywhere. Just this alone speeds up demo-making where I just can&#8217;t look at the default Times New Roman very long. Nothing against that typeface, it just makes demos look un-cared for.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Tab Size<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">html<\/span> {\n  <span class=\"hljs-attribute\">tab-size<\/span>: <span class=\"hljs-number\">2<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The fact that the default <code>tab-size<\/code> is 8 is whackadoo and needs to get tamped down. I get that taking advantage of wider screens can feel good but narrow screens are so much more common. Maybe I should use a <code>dvi<\/code> unit??<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Body Spacing<\/h3>\n\n\n\n<p>The body has an <code>8px<\/code> margin which is just awkward. I feel good about a more generous <code>2rem<\/code> padding kicking down to <code>1rem<\/code> at smaller screens. 500px is a heck of a magic number there, but feels generally right to me \u2014 it doesn&#8217;t <em>have<\/em> to sync up with other layout changes.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">body<\/span> {\n  <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0<\/span>;\n  <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">2rem<\/span>;\n  @media (width &lt; 500px) {\n    <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">1rem<\/span>;\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Box Sizing<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\">*,\n*<span class=\"hljs-selector-pseudo\">::before<\/span>,\n*<span class=\"hljs-selector-pseudo\">::after<\/span> {\n  <span class=\"hljs-attribute\">box-sizing<\/span>: border-box;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The ultimate classic thing for a reset. When I don&#8217;t do it up-front, I very regularly find myself needing to circle back and add it. I originally went with the <a href=\"https:\/\/css-tricks.com\/inheriting-box-sizing-probably-slightly-better-best-practice\/\">inheritance model<\/a>, but Miriam <a href=\"https:\/\/www.oddbird.net\/2025\/09\/04\/box-model\/\">convinced me not to<\/a>, basically by saying it &#8220;solves a problem that doesn\u2019t really exist.&#8221;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Hanging Punctuation<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">html<\/span> {\n  <span class=\"hljs-attribute\">hanging-punctuation<\/span>: first allow-end last;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>It&#8217;s just a little nicer looking so I&#8217;m <a href=\"https:\/\/chriscoyier.net\/2023\/11\/27\/the-hanging-punctuation-property-in-css\/\">taking my own advice<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Preventing Breakouts<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">html<\/span> {\n  <span class=\"hljs-attribute\">word-break<\/span>: break-word;\n}\n\n<span class=\"hljs-selector-tag\">pre<\/span> {\n  <span class=\"hljs-attribute\">white-space<\/span>: pre-wrap;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>These two are protective bits that essentially prevent long text (whether it wouldn&#8217;t naturally break or would be otherwise told not to break) from pushing a container wider than its parent would naturally be.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Headers<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">h1<\/span>,\n<span class=\"hljs-selector-tag\">h2<\/span> {\n  <span class=\"hljs-attribute\">font-weight<\/span>: <span class=\"hljs-number\">900<\/span>;\n  <span class=\"hljs-attribute\">letter-spacing<\/span>: -<span class=\"hljs-number\">0.02rem<\/span>;\n}\n<span class=\"hljs-selector-tag\">h1<\/span>,\n<span class=\"hljs-selector-tag\">h2<\/span>,\n<span class=\"hljs-selector-tag\">h3<\/span> {\n  <span class=\"hljs-attribute\">line-height<\/span>: <span class=\"hljs-number\">1.1<\/span>;\n}\n<span class=\"hljs-selector-tag\">h1<\/span>,\n<span class=\"hljs-selector-tag\">h2<\/span>,\n<span class=\"hljs-selector-tag\">h3<\/span>,\n<span class=\"hljs-selector-tag\">h4<\/span>,\n<span class=\"hljs-selector-tag\">h5<\/span>,\n<span class=\"hljs-selector-tag\">h6<\/span> <span class=\"hljs-comment\">\/* FUTURE :heading *\/<\/span> {\n  <span class=\"hljs-attribute\">text-wrap<\/span>: balance;\n  <span class=\"hljs-attribute\">margin-block-start<\/span>: <span class=\"hljs-number\">0<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The biggest two headers have a juiced up weight and are tucked in a little bit. The biggest three reduce their <code>line-height<\/code> (1.4, like the rest of the document, is too much for large headers). All the headers (which can be selected with <code>:heading<\/code> in the future) have wrapped balancing and have the margin <em>above<\/em> them knocked out. I tried leaving <em>most<\/em> of the user-agent stylesheet styles for stuff like this alone, but this one always annoys me.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Pretty Type<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">p<\/span>,\n<span class=\"hljs-selector-tag\">li<\/span>,\n<span class=\"hljs-selector-tag\">dd<\/span> {\n  <span class=\"hljs-attribute\">text-wrap<\/span>: pretty;\n  <span class=\"hljs-attribute\">max-inline-size<\/span>: <span class=\"hljs-number\">88ch<\/span>;\n}\n\n<span class=\"hljs-selector-tag\">sub<\/span>,\n<span class=\"hljs-selector-tag\">sup<\/span> {\n  <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">75%<\/span>;\n  <span class=\"hljs-attribute\">line-height<\/span>: <span class=\"hljs-number\">0<\/span>;\n  <span class=\"hljs-attribute\">position<\/span>: relative;\n  <span class=\"hljs-attribute\">vertical-align<\/span>: baseline;\n}\n<span class=\"hljs-selector-tag\">sub<\/span> {\n  <span class=\"hljs-attribute\">inset-block-end<\/span>: -<span class=\"hljs-number\">0.25em<\/span>;\n}\n<span class=\"hljs-selector-tag\">sup<\/span> {\n  <span class=\"hljs-attribute\">inset-block-start<\/span>: -<span class=\"hljs-number\">0.5em<\/span>;\n}\n\n<span class=\"hljs-selector-tag\">pre<\/span>,\n<span class=\"hljs-selector-tag\">code<\/span>,\n<span class=\"hljs-selector-tag\">kbd<\/span>,\n<span class=\"hljs-selector-tag\">samp<\/span> {\n  <span class=\"hljs-attribute\">font-family<\/span>: ui-monospace, SFMono-Regular, monospace;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We balanced the headings above, but we can use <code>pretty<\/code> on paragraph-y text for <a href=\"https:\/\/webkit.org\/blog\/16547\/better-typography-with-text-wrap-pretty\/\">better typography<\/a>. I&#8217;m also limiting the line length by limiting size in the direction of the flow. That <code>88ch<\/code> still probably <em>too<\/em> wide for most text. I just picked the Back to the Future number, but it&#8217;s <a href=\"https:\/\/blog.glyph.im\/2025\/08\/the-best-line-length.html\">not without merit<\/a>). I&#8217;m not trying to be ultra-opinionated in this case, just protective.<\/p>\n\n\n\n<p>Those <code>sub<\/code> and <code>sup<\/code> styles date all the way back to the original <a href=\"https:\/\/github.com\/necolas\/normalize.css\">Normalize<\/a>. I&#8217;m a fan because otherwise those elements can cause an extra-thick line-height in the middle of a paragraph and it&#8217;s quite unsightly. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Chilled Out Underlines<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">a<\/span> {\n  <span class=\"hljs-attribute\">color<\/span>: <span class=\"hljs-built_in\">oklch<\/span>(<span class=\"hljs-number\">0.68<\/span> <span class=\"hljs-number\">0.17<\/span> <span class=\"hljs-number\">228<\/span>);\n  <span class=\"hljs-attribute\">text-underline-offset<\/span>: <span class=\"hljs-number\">2px<\/span>;\n  &amp;:not(:is(:hover, :focus)) {\n    <span class=\"hljs-attribute\">text-decoration-color<\/span>: <span class=\"hljs-built_in\">color-mix<\/span>(in srgb, currentColor, transparent <span class=\"hljs-number\">50%<\/span>);\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><a href=\"https:\/\/frontendmasters.com\/blog\/chilled-out-text-underlines\/\">You know I had to.<\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Lists<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">ul<\/span>,\n<span class=\"hljs-selector-tag\">ol<\/span>,\n<span class=\"hljs-selector-tag\">dl<\/span> {\n  <span class=\"hljs-attribute\">margin<\/span>: <span class=\"hljs-number\">0<\/span>;\n  <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">0<\/span>;\n  <span class=\"hljs-attribute\">list-style<\/span>: inside;\n  ul,\n  ol,\n  dl {\n    <span class=\"hljs-attribute\">padding-inline-start<\/span>: <span class=\"hljs-number\">2ch<\/span>;\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>I like my list bullets inside the container and nested lists indented just a bit, matching the <code>tab-size<\/code>. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Media<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">img<\/span>,\n<span class=\"hljs-selector-tag\">video<\/span>,\n<span class=\"hljs-selector-tag\">iframe<\/span> {\n  <span class=\"hljs-attribute\">display<\/span>: block;\n  <span class=\"hljs-attribute\">max-inline-size<\/span>: <span class=\"hljs-number\">100%<\/span>;\n  <span class=\"hljs-attribute\">block-size<\/span>: auto;\n  <span class=\"hljs-attribute\">border-style<\/span>: none;\n}\n\n<span class=\"hljs-selector-tag\">figure<\/span> {\n  <span class=\"hljs-attribute\">inline-size<\/span>: fit-content;\n  <span class=\"hljs-attribute\">margin-inline<\/span>: auto;\n}\n<span class=\"hljs-selector-tag\">figcaption<\/span> {\n  <span class=\"hljs-attribute\">contain<\/span>: inline-size;\n  <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">90%<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>I&#8217;m being protective here with my media elements, making sure they don&#8217;t break out of a container. Then if you are potentially limiting the width (inline-size), you need to let the height be free (block-size) so you don&#8217;t get squishing.<\/p>\n\n\n\n<p>The figure\/figcaption stuff is <a href=\"https:\/\/frontendmasters.com\/blog\/the-figcaption-problem\/\">from this whole journey<\/a> and I think it makes sense broadly.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Forms<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">input<\/span>,\n<span class=\"hljs-selector-tag\">select<\/span>,\n<span class=\"hljs-selector-tag\">textarea<\/span>,\n<span class=\"hljs-selector-tag\">button<\/span> {\n  <span class=\"hljs-attribute\">font<\/span>: inherit;\n  <span class=\"hljs-comment\">\/* FUTURE: apperance: base; *\/<\/span>\n}\n<span class=\"hljs-selector-tag\">label<\/span> {\n  <span class=\"hljs-attribute\">display<\/span>: block;\n}\n<span class=\"hljs-selector-tag\">input<\/span><span class=\"hljs-selector-pseudo\">:not(<\/span>\n  <span class=\"hljs-selector-pseudo\">:where(<\/span>\n    <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"submit\"<\/span>]<\/span>,\n    <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"checkbox\"<\/span>]<\/span>,\n    <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"radio\"<\/span>]<\/span>,\n    <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"button\"<\/span>]<\/span>,\n    <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"reset\"<\/span>]<\/span>\n  )\n) {\n  <span class=\"hljs-attribute\">inline-size<\/span>: <span class=\"hljs-number\">100%<\/span>;\n}\n<span class=\"hljs-selector-tag\">button<\/span>,\n<span class=\"hljs-selector-tag\">input<\/span><span class=\"hljs-selector-pseudo\">:where(<\/span>\n  <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"submit\"<\/span>]<\/span>,\n  <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"reset\"<\/span>]<\/span>,\n  <span class=\"hljs-selector-attr\">&#91;type=<span class=\"hljs-string\">\"button\"<\/span>]<\/span>\n) {\n  <span class=\"hljs-attribute\">background<\/span>: CanvasText;\n  <span class=\"hljs-attribute\">color<\/span>: Canvas;\n  <span class=\"hljs-attribute\">border<\/span>: <span class=\"hljs-number\">1px<\/span> solid transparent;\n}\n<span class=\"hljs-selector-tag\">textarea<\/span> {\n  <span class=\"hljs-attribute\">field-sizing<\/span>: content;\n  <span class=\"hljs-attribute\">min-block-size<\/span>: <span class=\"hljs-number\">5<\/span>lh;\n  <span class=\"hljs-attribute\">inline-size<\/span>: <span class=\"hljs-number\">100%<\/span>;\n  <span class=\"hljs-attribute\">max-inline-size<\/span>: <span class=\"hljs-number\">100%<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The first bit has form elements use the same basic typography as the rest of the site, which is a big improvement for consistency in a UI if you ask me. This is opinionated toward single-column full-width forms <a href=\"https:\/\/www.lukew.com\/resources\/web_form_design.asp\">where research convinced me<\/a> is just better for users. Buttons flop out light\/dark colors and have an (invisible) border (which becomes visible in Windows High Contrast mode, so it&#8217;s an accessibility thing).<\/p>\n\n\n\n<p>Using <code>field-sizing<\/code> on textareas is just correct, but you need a little extra there to make sure it doesn&#8217;t collapse.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">SVG<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">svg<\/span> {\n  <span class=\"hljs-attribute\">fill<\/span>: currentColor;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>I&#8217;m not doing much for SVG. That could evolve. But for now I do like it when SVG icons color comes along for the ride and dare-I-say <em>most<\/em> icons use <code>fill<\/code> rather than <code>stroke<\/code> for their main coloring.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Hidden (is a lie)<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-attr\">&#91;hidden]<\/span> {\n  <span class=\"hljs-attribute\">display<\/span>: none <span class=\"hljs-meta\">!important<\/span>;\n}\n<span class=\"hljs-selector-class\">.screenreader-only<\/span><span class=\"hljs-selector-pseudo\">:not(<\/span><span class=\"hljs-selector-pseudo\">:focus)<\/span><span class=\"hljs-selector-pseudo\">:not(<\/span><span class=\"hljs-selector-pseudo\">:active)<\/span> {\n  <span class=\"hljs-attribute\">clip<\/span>: <span class=\"hljs-built_in\">rect<\/span>(<span class=\"hljs-number\">0<\/span> <span class=\"hljs-number\">0<\/span> <span class=\"hljs-number\">0<\/span> <span class=\"hljs-number\">0<\/span>);\n  <span class=\"hljs-attribute\">clip-path<\/span>: <span class=\"hljs-built_in\">inset<\/span>(<span class=\"hljs-number\">50%<\/span>);\n  <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">1px<\/span>;\n  <span class=\"hljs-attribute\">overflow<\/span>: hidden;\n  <span class=\"hljs-attribute\">position<\/span>: absolute;\n  <span class=\"hljs-attribute\">white-space<\/span>: nowrap;\n  <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">1px<\/span>;\n}\n<span class=\"hljs-selector-pseudo\">:focus-visible<\/span> {\n  <span class=\"hljs-attribute\">outline-offset<\/span>: <span class=\"hljs-number\">2px<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><a href=\"https:\/\/meowni.ca\/hidden.is.a.lie.html\">Monica Dinculescu classic.<\/a> I think it&#8217;s worth being able to use (and trust) this attribute.<\/p>\n\n\n\n<p>Plus, you gotta have an <a href=\"https:\/\/www.scottohara.me\/blog\/2017\/04\/14\/inclusively-hidden.html\">accessible hiding class<\/a>. As a little bonus I think it looks a little nicer to push the default outlines away from elements a bit when they are tabbed to (with the keyboard). <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Horizontal Rules<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">hr<\/span> {\n  <span class=\"hljs-attribute\">border-style<\/span>: solid;\n  <span class=\"hljs-attribute\">border-width<\/span>: <span class=\"hljs-number\">1px<\/span> <span class=\"hljs-number\">0<\/span> <span class=\"hljs-number\">0<\/span>;\n  <span class=\"hljs-attribute\">color<\/span>: inherit;\n  <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">0<\/span>;\n  <span class=\"hljs-attribute\">overflow<\/span>: visible;\n  <span class=\"hljs-attribute\">margin-block<\/span>: <span class=\"hljs-number\">2.5rem<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>I hate the default weird beveled look. I just want a line with lots of space above and below it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">No Headbutting<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-pseudo\">:target<\/span> {\n  <span class=\"hljs-attribute\">scroll-margin<\/span>: <span class=\"hljs-number\">3<\/span>rlh;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>I also hate it when you #hash-link to something and it&#8217;s smashed to the edge of the browser window, potentially even hurting the context of why you&#8217;re linking to it. This is a magic number, but it feels good usually.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Tables<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">table<\/span> {\n  <span class=\"hljs-attribute\">caption-side<\/span>: bottom;\n  <span class=\"hljs-attribute\">border-collapse<\/span>: collapse;\n  td {\n    <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">90%<\/span>;\n  }\n  <span class=\"hljs-selector-tag\">td<\/span>,\n  <span class=\"hljs-selector-tag\">th<\/span> {\n    <span class=\"hljs-attribute\">word-break<\/span>: normal;\n    <span class=\"hljs-attribute\">border<\/span>: <span class=\"hljs-number\">1px<\/span> solid gray;\n    <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">0.5rem<\/span>;\n  }\n}\n<span class=\"hljs-selector-attr\">&#91;role=<span class=\"hljs-string\">\"region\"<\/span>]<\/span><span class=\"hljs-selector-attr\">&#91;aria-labelledby]<\/span><span class=\"hljs-selector-attr\">&#91;tabindex]<\/span> {\n  <span class=\"hljs-attribute\">overflow<\/span>: auto;\n}\n<span class=\"hljs-selector-tag\">caption<\/span> {\n  <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">90%<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This kicks the <code>&lt;caption&gt;<\/code> to the bottom of the table, where you&#8217;d normally put a <code>&lt;figcaption&gt;<\/code> so it just looks\/feels better. Then it smashes the <code>border<\/code> of table cells together which just feels correct. Then it sets you up for <a href=\"https:\/\/adrianroselli.com\/2020\/11\/under-engineered-responsive-tables.html\">proper very basic responsive tables<\/a>. Again, protective stuff.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Motion<\/h3>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">@media (prefers-reduced-motion: no-preference) {\n  @view-transition {\n    navigation: auto;\n  }\n    \n  html {\n    interpolate-size: allow-keywords;\n    &amp;:focus-within {\n      scroll-behavior: smooth;\n    }\n  }\n}<\/code><\/span><\/pre>\n\n\n<p>This opt-in&#8217;s to multi-page view transitions which you probably almost always want, but only does it if the user hasn&#8217;t said they prefer reduced motion through their operating system. I think that&#8217;s highly appropriate here because it can make the <em>whole screen move<\/em> which is the riskiest of all motion-sickness stuff in my experience.<\/p>\n\n\n\n<p>This also opts-in to <a href=\"https:\/\/frontendmasters.com\/blog\/what-you-need-to-know-about-modern-css-2025-edition\/#animate-to-auto\">animate-to-auto<\/a> which just rules and allows for smooth-scrolling, but only when the page is focused (so doesn&#8217;t do that when you&#8217;re using &#8220;find&#8221; in the browser itself to search the page.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Critique?<\/h2>\n\n\n\n<p>What do you like and dislike? What would you do differently? I <em>love<\/em> scrutinizing other people&#8217;s starters\/resets, so I&#8217;m certainly open to the same on mine.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A fairly opinionated CSS starter by Chris, following a set of personal principals to guide what is in there and what isn&#8217;t.  <\/p>\n","protected":false},"author":1,"featured_media":7255,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[7,405],"class_list":["post-7245","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-css","tag-starter"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/09\/The-Coyier-Starter-1.jpg?fit=1140%2C676&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/7245","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=7245"}],"version-history":[{"count":18,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/7245\/revisions"}],"predecessor-version":[{"id":7385,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/7245\/revisions\/7385"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/7255"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=7245"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=7245"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=7245"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}