├── cases ├── reset.css ├── 100vh │ ├── README.md │ └── index.html ├── typography │ ├── index.html │ └── README.md ├── quantity │ ├── README.md │ └── index.html └── fluid-typography │ └── index.html ├── LICENSE └── README.md /cases/reset.css: -------------------------------------------------------------------------------- 1 | * { 2 | /* https://www.oddbird.net/2025/09/04/box-model/ */ 3 | box-sizing: border-box; 4 | } 5 | 6 | html { 7 | /* https://gomakethings.com/prevent-scrollbar-jump/ */ 8 | scrollbar-gutter: stable; 9 | 10 | /* https://dbushell.com/2024/11/05/webkit-font-smoothing/ */ 11 | -webkit-font-smoothing: antialiased; 12 | 13 | /* https://pawelgrzybek.com/the-css-reset-again/ */ 14 | -webkit-text-size-adjust: none; 15 | text-size-adjust: none; 16 | } 17 | -------------------------------------------------------------------------------- /cases/100vh/README.md: -------------------------------------------------------------------------------- 1 | # 100vh in iOS 2 | 3 | Based in 4 | [CSS fix for 100vh in mobile WebKit](https://allthingssmitty.com/2020/05/11/css-fix-for-100vh-in-mobile-webkit/) 5 | and the [PostCSS plugin](https://github.com/postcss/postcss-100vh-fix) 6 | 7 | ```css 8 | body { 9 | height: 100vh; 10 | } 11 | 12 | /* Apply the hack only in Safari */ 13 | @supports (-webkit-touch-callout: none) { 14 | body { 15 | height: -webkit-fill-available; 16 | } 17 | } 18 | ``` 19 | 20 | [Online demo](https://oscarotero.github.io/css-style-guide/cases/100vh/) 21 | -------------------------------------------------------------------------------- /cases/typography/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Typography test 7 | 8 | 17 | 18 | 19 |

Normal Caps, Small Caps Demo

20 | 21 | 22 | -------------------------------------------------------------------------------- /cases/100vh/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | iPhone 100vh 5 | 6 | 7 | 30 | 31 | 32 |
Header goes here
33 |
Main goes here
34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /cases/quantity/README.md: -------------------------------------------------------------------------------- 1 | # Quantity queries 2 | 3 | This guide allows to create quantity queries using only css. 4 | 5 | Based in 6 | [Use Quantity Queries to Make Your CSS Quantity-Aware](http://www.hongkiat.com/blog/quantity-queries-css-quantity-aware/) 7 | article. 8 | 9 | ```css 10 | /* At least 5 */ 11 | ul li:nth-last-child(n+5), 12 | ul li:nth-last-child(n+5) ~ li { 13 | border: 2px dashed; 14 | } 15 | 16 | /* At most 5 */ 17 | ul li:nth-last-child(-n+5):first-child, 18 | ul li:nth-last-child(-n+5):first-child ~ li { 19 | background-color: yellow; 20 | } 21 | 22 | /* Between 5 and 8 */ 23 | ul li:nth-last-child(n+5):nth-last-child(-n+8):first-child, 24 | ul li:nth-last-child(n+5):nth-last-child(-n+8):first-child ~ li { 25 | font-weight: bold; 26 | } 27 | 28 | /* Exactly 5 */ 29 | ul li:nth-last-child(5):first-child, 30 | ul li:nth-last-child(5):first-child ~ li { 31 | text-decoration: underline; 32 | } 33 | ``` 34 | 35 | [Online demo](https://oscarotero.github.io/css-style-guide/cases/cuantity/) 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Oscar Otero 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /cases/typography/README.md: -------------------------------------------------------------------------------- 1 | # Typography 2 | 3 | Guide of advanced css features for typography. 4 | 5 | ## Caps 6 | 7 | More info: 8 | [Font Variant Caps](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-caps) 9 | 10 | To use real small caps: 11 | 12 | ```css 13 | .small-caps { 14 | font-variant-caps: small-caps; 15 | } 16 | ``` 17 | 18 | ## Numbers 19 | 20 | More info: 21 | [Font Variant Numeric](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-numeric) 22 | 23 | ### Lining / old style 24 | 25 | Lining figures are uppercase numbers. Old style figures are numbers to use 26 | inside a body text. 27 | 28 | ```css 29 | .lining { 30 | font-variant-numeric: lining-nums; 31 | } 32 | 33 | .old-style { 34 | font-variant-numeric: oldstyle-nums; 35 | } 36 | ``` 37 | 38 | ### Proportional / tabular 39 | 40 | Proportional means numbers with different widths. Tabular numbers align 41 | horizontally no matter the number. 42 | 43 | ```css 44 | .proportional { 45 | font-variant-numeric: proportional-nums; 46 | } 47 | 48 | .tabular { 49 | font-variant-numeric: tabular-nums; 50 | } 51 | ``` 52 | 53 | ## Ligatures 54 | 55 | More info: 56 | [Font Variant Ligatures](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant-ligatures) 57 | 58 | The common ligatures are enabled by default in most browsers. You can enable 59 | also other different ligatures: 60 | 61 | ### Discretional / contextual 62 | 63 | Discretional ligatures are more ornamental. Contextual are more common in script 64 | typefaces, and are used to make the text look "natural" 65 | 66 | ```css 67 | .discretional { 68 | font-variant-ligatures: discretionary-ligatures; 69 | } 70 | 71 | .contextual { 72 | font-variant-ligatures: contextual; 73 | } 74 | ``` 75 | 76 | ## Other features 77 | 78 | System fonts 79 | 80 | ```css 81 | .system { 82 | font-family: -apple-system, system-ui, sans-serif; 83 | } 84 | ``` 85 | 86 | Text decoration skip 87 | 88 | ```css 89 | .skip { 90 | text-decoration-skip-ink: auto; 91 | -webkit-text-decoration-skip: ink; /* Safari */ 92 | } 93 | ``` 94 | 95 | [Online demo](https://oscarotero.github.io/css-style-guide/cases/typography/) 96 | -------------------------------------------------------------------------------- /cases/quantity/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | CSS selectors test 7 | 8 | 47 | 48 | 49 |

Cuantity queries

50 |

51 | At least 5 52 |

53 |

54 | At most 5 55 |

56 |

57 | Exactly 5 58 |

59 |

60 | Between 5 and 8 61 |

62 | 69 | 75 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /cases/fluid-typography/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Utopia maths in CSS 7 | 54 | 55 | 56 |

Ola

57 |

Ola

58 |

Ola

59 | 60 | 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSS Style guide 2 | 3 | This is the style guide that I use to write CSS. It's inspired by other 4 | methodologies like BEM, SMACSS, OOCSS, etc but more simple. The aim of this 5 | guide is **write modular, scalable and maintainable CSS.** 6 | 7 | ## Components 8 | 9 | CSS components (a.k.a. modules, objects, etc) are defined with classes. 10 | 11 | ```css 12 | /* The 'article' component */ 13 | .article {} 14 | ``` 15 | 16 | Don't use `-` character for component names. If you want to differentiate words, 17 | use _camelCase_ or underscores: 18 | 19 | ```css 20 | /* The 'image carousel' component */ 21 | .imageCarousel {} 22 | 23 | /* Alternative naming if you don't like camelCase */ 24 | .image_carousel {} 25 | ``` 26 | 27 | Components may have properties. The properties are joined to the component name 28 | with a `-`. Example: 29 | 30 | ```css 31 | .article { 32 | /* styles of the component */ 33 | } 34 | 35 | .article-header { 36 | /* styles of the component's property */ 37 | } 38 | ``` 39 | 40 | Like component names, properties shouldn't have `-` characters: 41 | 42 | ```css 43 | .article-mainImage { 44 | /* styles of the mainImage property of article component */ 45 | } 46 | ``` 47 | 48 | > [!note] 49 | > 50 | > The use of camelCase notation allows to use a simple join character unlike BEM 51 | > that needs two underscores (`.article__header__title`). 52 | 53 | This allows to add sub-properties if it's needed: 54 | 55 | ```css 56 | .article-header-title {} 57 | ``` 58 | 59 | ```html 60 |
61 |
62 |

63 | The title 64 |

65 |
66 |
67 | ``` 68 | 69 | Don't use use sub-properties if you really don't need to. The previous example 70 | is clearer as following: 71 | 72 | ```html 73 |
74 |
75 |

76 | The title 77 |

78 |
79 |
80 | ``` 81 | 82 | ## Modifiers 83 | 84 | Components and properties may have modifiers. Modifiers are used to change 85 | styles under some contexts or status. Unlike, for instance, BEM, modifiers are 86 | independent classes that you can combine with components and properties. These 87 | classes should start with `.is-*` and `.has-*`. 88 | 89 | The `.is-*` modifier changes the element with a specific status. Some examples: 90 | 91 | ```css 92 | .article.is-hidden { 93 | display: none; 94 | } 95 | 96 | .article-header.is-important { 97 | font-weight: bold; 98 | } 99 | 100 | .article p.is-highlighted { 101 | background: yellow; 102 | } 103 | ``` 104 | 105 | ```html 106 | 109 | ``` 110 | 111 | The `.has-*` modifier is used to change the element according to its content. 112 | Example: 113 | 114 | ```css 115 | .article { 116 | width: 500px; 117 | } 118 | 119 | .article.has-video { 120 | width: 900px; 121 | } 122 | ``` 123 | 124 | ```html 125 |
126 | 127 |
128 | ``` 129 | 130 | The modifiers must be declared always combined with the components/properties: 131 | 132 | ```css 133 | /* wrong */ 134 | .has-video { 135 | width: 900px; 136 | } 137 | 138 | /* right */ 139 | .article.has-video { 140 | width: 900px; 141 | } 142 | ``` 143 | 144 | This has two advantages: 145 | 146 | - Increments the priority of the selector. 147 | - Allows to create different styles for the same modifier combined with 148 | different components/properties. 149 | 150 | There may be global modifiers if needed: 151 | 152 | ```css 153 | /* This is a global modifier, it can be combined with any component */ 154 | .is-hidden { 155 | display: none; 156 | } 157 | ``` 158 | 159 | Some `has-` modifiers can be replaced with the 160 | [`:has()` selector](https://developer.mozilla.org/en-US/docs/Web/CSS/:has) 161 | supported by all modern browsers: 162 | 163 | ```css 164 | /* Old way */ 165 | .article.has-video { 166 | width: 900px; 167 | } 168 | 169 | /* Modern way */ 170 | .article:has(.article-video) { 171 | width: 900px; 172 | } 173 | ``` 174 | 175 | ## Layouts 176 | 177 | By convention, CSS styles used only for layout purposes must use the `.ly-*` 178 | namespace. Example of the `2columns` layout with two properties: `navigation` 179 | and `content`: 180 | 181 | ```css 182 | .ly-2columns { 183 | display: grid; 184 | grid-template-areas: "navigation content"; 185 | grid-template-columns: 400px 1fr; 186 | } 187 | .ly-2columns-navigation { 188 | grid-area: navigation; 189 | } 190 | .ly-2columns-content { 191 | grid-area: content; 192 | } 193 | ``` 194 | 195 | ```html 196 |
197 | 198 |
...
199 |
200 | ``` 201 | 202 | ## CSS + JS 203 | 204 | The CSS classes can be used by JavaScript to select elements. To prevent 205 | conflict between CSS and JS, **the classes used by JavaScript should not be used 206 | by CSS, and viceversa**. Because that, there's the `.js-*` namespace: 207 | 208 | ```html 209 |
210 |

Hello world

211 |
212 | 213 |
214 | Other popup 215 |
216 | ``` 217 | 218 | ```js 219 | document.querySelector(".js-popup")?.style.display = "block"; 220 | ``` 221 | 222 | It's recomended to separate styling classes and functionality classes. This 223 | doesn't mean JavaScript can not use styling classes, but only for styling 224 | purposes: 225 | 226 | ```js 227 | document.querySelector(".article")?.classList.add("is-hidden"); 228 | ``` 229 | 230 | ## !important 231 | 232 | The `!important` flag **is not recommended,** but may be needed in few edge 233 | cases. Every time we use it, we should include a comment explaining the reason, 234 | so it can be removed in the future. 235 | 236 | ```css 237 | .popup-title { 238 | font-weight: bold 239 | !important; /* This overrides the inline style applied by the plugin popup */ 240 | } 241 | ``` 242 | 243 | ## Imports 244 | 245 | In order to avoid problems with the selectors priority, the main CSS file should 246 | import the nested CSS files in the following order: 247 | 248 | - global styles (reset, variables, normalize, etc) 249 | - components 250 | - global modifiers 251 | - hacks 252 | 253 | Example: 254 | 255 | ```css 256 | /* Global styles */ 257 | @import "normalize.css"; 258 | @import "reset.css"; 259 | 260 | /* Components */ 261 | @import "components/article.css"; 262 | @import "components/comments.css"; 263 | 264 | /* Global modifiers and hacks */ 265 | @import "modifiers.css"; 266 | @import "ie.css"; 267 | ``` 268 | 269 | ## Layers 270 | 271 | Additionally, we can use CSS layers for better organization and priority: 272 | 273 | ```css 274 | @layer global { 275 | /* Normalize, reset */ 276 | } 277 | 278 | @layer components { 279 | /* Components */ 280 | } 281 | 282 | @layer utils { 283 | /* Utils, global modifiers, hacks, etc */ 284 | } 285 | ``` 286 | 287 | --- 288 | 289 | Other notes: 290 | 291 | - [100vh](cases/100vh) 292 | - [quantity](cases/quantity) 293 | - [typography](cases/typography) 294 | - [select (filamentgroup)](https://github.com/filamentgroup/select-css) 295 | --------------------------------------------------------------------------------