└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Hiccup 2 | 3 | A super strict yet probably too lenient methodology for writing maintainable CSS. 4 | 5 | 6 | 7 | ### Intention 8 | 9 | To encourage minimal markup and help write concise and maintainable css. 10 | 11 | ### Why 12 | 13 | Why not use just another CSS naming convention like BEM or OOCSS. I found that they were either too dictating, too restrictive, or just made my class names rediculosly huge like `.some-class__child-class--class-modifier` really??? O.o who wants that? 14 | 15 | ### How 16 | 17 | So how does it work? Please bear in mind that this is a living document and that it is subject to change. 18 | 19 | There are six kinds of classes used with the hiccup methodology: 20 | 21 | * Components 22 | * Sub-components - `*` 23 | * Children - `_` & `~` 24 | * Modifiers - `&` 25 | * States - `+` 26 | * Globals - `!` 27 | 28 | **Note**: we explicitly avoid using the `-` to identify classes so it can be used in class names (for example `.side-menu`) without gettign confusing. 29 | 30 | We differentiate these class types using prefixes as follows: 31 | 32 | **Globals**: 33 | 34 | ```scss 35 | .\!font-large { 36 | font-size: 30px; 37 | } 38 | ``` 39 | 40 | Globals are the only selector not typecast and that do not require the direct descendant selector as they can be used globally. 41 | 42 | **Components**: 43 | 44 | ```scss 45 | div.menu { 46 | background-color: lime; 47 | display: inline-block; 48 | min-width: 350px; 49 | height: 100vh; 50 | float: left; 51 | } 52 | ``` 53 | 54 | All classes **excluding globals** should be typecast to a certain element like `div.menu` why is this? 55 | When we write CSS we assume certain properties about the element we are going to apply the class to (for example that a `div` is `display: block;`). This means despite how CSS is usually written there is an intended HTML structure for said CSS. 56 | To strictly enforce the intended structure we require all classes be element typecast to force the correct semantics. 57 | 58 | As an added bonus this also speeds up the browsers CSS selector engine. 59 | 60 | **Children**: 61 | 62 | ```scss 63 | div.menu { 64 | //... 65 | a._menu\~link { 66 | display: block; 67 | padding: 10px; 68 | color: white; 69 | background-color: deepskyblue; 70 | border-bottom: 2px dashed white; 71 | text-decoration: none; 72 | } 73 | } 74 | ``` 75 | 76 | Like BEM we identify children using the `_` however we do this slightly differently using the `_` at the start of the class name followed by the parent component name with the `~` appended and then the class name of the child. This is so you can quickly differentiate between a new component and a components child. 77 | 78 | **Sub-components** 79 | 80 | ```scss 81 | div.\*profile { 82 | //... 83 | div._\*profile\~image { 84 | //... 85 | img { 86 | //... 87 | } 88 | } 89 | } 90 | ``` 91 | 92 | Sub-components are similar to components but with **two** big differences. 93 | 94 | **One**: sub-components explicity require that no components or sub-components be nested within them, this means you do not need to accomodate for any unknown markup within your component. 95 | 96 | _When is this prudent?_ 97 | 98 | Usually for elements where you may be utilizing `position: absolute;` (or other more explicit CSS properties) and you know exactly the elements you intended to have in the component and you only want to accomodated for them and no extra. 99 | 100 | **Two**: sub-components allow their children to target elements without classes for example: 101 | 102 | ```scss 103 | div.\*profile { 104 | //... 105 | div._\*profile\~image { 106 | //... 107 | img { 108 | //... 109 | } 110 | span { 111 | //... 112 | } 113 | } 114 | } 115 | ``` 116 | 117 | _Why bother?_ 118 | 119 | When I set out to create hiccup one of my biggest frustrations with BEM was for things like a sub-component where I knew nothing would ever be nested within the component but I still had to adhere to giving every element I styled a class name including **wrapping elements** which make for (IMHO) terrible markup. Who wants to read: 120 | 121 | ```html 122 |
123 |
124 | ... 125 | 126 | 127 | Title text 128 | 129 | 130 |
131 |
132 | ``` 133 | 134 | With hiccup that becomes the following: 135 | 136 | ```html 137 |
138 |
139 | ... 140 | 141 | 142 | Title Text 143 | 144 | 145 |
146 |
147 | ``` 148 | 149 | Because we know the exact markup our sub-component will contain we are free to target the `img` directly to apply whatever additional styles we need. 150 | 151 | If you are adverse to targeting elements without classes that is fine sub-components still utilize children just like regular components. If you were to avoid targeting elements without classes the only difference between your sub-components and your regular components would be that your sub-components would require components and sub-components to not be nested beneath them. 152 | 153 | **Modifiers**: 154 | 155 | ```scss 156 | div.menu { 157 | //... 158 | a._menu\~link { 159 | &.\&active { 160 | background-color: purple; 161 | } 162 | } 163 | } 164 | ``` 165 | 166 | Modifiers will never by typecast because they will always be applied with another class whether it is a component or a child. 167 | 168 | **Note**: modifiers can be applied to Components, Sub-components, and Children. 169 | 170 | **States**: 171 | 172 | ```scss 173 | div.menu { 174 | //... 175 | &.\+shrunk { 176 | a._menu\~link { 177 | //... 178 | } 179 | } 180 | } 181 | ``` 182 | 183 | A state works similar to a modifier but it is top level and instead of just modifying the element it is applied to it allows you to modify its children and their modifiers. 184 | 185 | **Note**: states can be applied to Components and Sub-components. 186 | 187 | 188 | 189 | ### When should something become a component? 190 | 191 | There are two common instances where a child should become a component/sub-component. 192 | 193 | 1) When you are repeating styles between components: 194 | 195 | ```scss 196 | div.profile { 197 | a._profile\~email-link { 198 | padding: 10px 15px; 199 | background-color: lime; 200 | &:hover { 201 | background-color: deeppink; 202 | } 203 | } 204 | } 205 | ``` 206 | 207 | ```scss 208 | form.contact-form { 209 | button._contact-form\~submit { 210 | padding: 10px 15px; 211 | background-color: lime; 212 | &:hover { 213 | background-color: deeppink; 214 | } 215 | } 216 | } 217 | ``` 218 | 219 | Seeing as these styles are the same they can become: 220 | 221 | ```scss 222 | a, button { 223 | &.\*button { 224 | padding: 10px 15px; 225 | background-color: lime; 226 | &:hover { 227 | background-color: deeppink; 228 | } 229 | } 230 | } 231 | ``` 232 | 233 | 2) When you have up to two children that belong within another child: 234 | 235 | ```scss 236 | div.certificate { 237 | div._certificate\~profile { 238 | //... 239 | } 240 | div._certificate\~profile-image { 241 | //... 242 | } 243 | div._certificate\~profile-title { 244 | //... 245 | } 246 | } 247 | ``` 248 | 249 | With the above `div._certificate\~profile-image` and `div._certificate\~profile-title` are intended to be nested within `div._certificate\~profile`. This would be okay. 250 | 251 | ```scss 252 | div.certificate { 253 | div._certificate\~profile { 254 | //... 255 | } 256 | div._certificate\~profile-image { 257 | //... 258 | } 259 | div._certificate\~profile-title { 260 | //... 261 | } 262 | div._certificate\~profile-content { 263 | //... 264 | } 265 | div._certificate\~profile-social-media { 266 | //... 267 | } 268 | } 269 | ``` 270 | 271 | Where as with the above it would probably make sense to extract `profile` out to its own component: 272 | 273 | ### Why so complicated? 274 | 275 | _Wouldn't it be easier to drop the concept of Sub-components and States and move towards a more BEM like structure?_ 276 | 277 | In short YES. But we won't, why? CSS is global meaning that the level of specificity is up to you. Hiccup is more specific / complicated than most other naming conventions not because they do not have these issues but because they do not address them well. Yes more specific CSS is harder to write but it is also easier to maintain. 278 | 279 | ### Conclusion 280 | 281 | Hiccup is still in it's very early days and there is still plenty of room to improve so any suggetions / edits please fire through a PR. 282 | --------------------------------------------------------------------------------