├── LICENSE ├── README.md └── typecsset.scss /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 Harry Roberts 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Typecsset (v0.3.0) 2 | 3 | **Typecsset (type·set, /ˈtīpˌset/) is a small Sass library for 4 | setting type on the web.** 5 | 6 | It gives you an automatic, pixel-perfect, baseline grid across all textual HTML 7 | elements based entirely on just a few settings of your choice. Baseline grids 8 | without the headaches. 9 | 10 | ## Demo 11 | 12 | * [View demo](http://csswizardry.com/typecsset/) 13 | * [View demo code](https://github.com/csswizardry/typecsset/tree/gh-pages) 14 | 15 | ## Implementation 16 | 17 | Using Typecsset couldn’t be easier. Download the Sass file, predefine any 18 | settings, `@import` it into your project, _go!_ 19 | 20 | ```scss 21 | $typecsset-base-font-size: 18px; 22 | $typecsset-base-line-height: 27px; 23 | 24 | [Your own CSS] 25 | 26 | @import "path/to/typecsset"; 27 | 28 | [More of your own CSS] 29 | ``` 30 | 31 | **[Example](https://github.com/csswizardry/typecsset/blob/gh-pages/style.scss)** 32 | 33 | ### Precision 34 | 35 | Due to the nature of unitless and relative values, you will end up with a lot of 36 | floats as opposed to integers (e.g. `line-height: 1.333;` instead of 37 | `line-height: 24px;`). In order to ensure that browsers can work these values 38 | out as closely as possible to the pixel, thus avoiding rounding errors, I 39 | recommend compiling your Sass with the `--precision` flag set to `7`, e.g.: 40 | 41 | sass --watch typecsset.scss:typecsset.css --style expanded --precision 7 42 | 43 | ## Settings 44 | 45 | All Typecsset’s settings are stored in namespaced variables (e.g. 46 | `$typecsset-base-font-size`). You should avoid modifying these directly, as to 47 | do so would inhibit your ability to smoothly update the library. If you would 48 | like to modify the default settings in Typecsset, predefine them _before_ you 49 | import the library, as above. 50 | 51 | There are certain settings in Typecsset that should not and cannot be 52 | overridden, as they are fundamental to the way the library works. These settings 53 | are, however, based upon the settings you _can_ modify. 54 | 55 | ### `$typecsset-base-font-size` 56 | 57 | This is the base font size you would like your project to have. Set this in 58 | pixels: Typecsset will convert it to the relevant units for you. 59 | 60 | ### `$typecsset-base-line-height` 61 | 62 | This is the base line height you would like your project to take. Again, define 63 | this in pixels: Typecsset will convert it into a unitless value for you. 64 | 65 | This `$typecsset-base-line-height` value is the most important one in the whole 66 | library—it defines and underpins your whole vertical rhythm. Everything 67 | (`margins`, `line-height`s, etc.) will be based upon units of this number in 68 | order to maintain a consistent and harmonious vertical rhythm. 69 | 70 | ### `$typecsset-h[1–6]-size` 71 | 72 | These settings, predictably, contain the desired font sizes for your headings 73 | one-through-six. Again, they are set in pixels because the library will pick 74 | them up and convert them into rems later on. 75 | 76 | ### `$typecsset-indented-paragraphs` 77 | 78 | This is a simple boolean to toggle between indented—as you traditionally find in 79 | print—or simply spaced—more common on the web—paragraphs. 80 | 81 | ### `$typecsset-show-baseline` 82 | 83 | Another boolean which will simply turn a baseline grid either on or off. The 84 | image used for the grid is provided by [Basehold.it](http://basehold.it/), and 85 | is based on the value of `$typecsset-base-line-height`. It will automatically 86 | update itself whenever you modify the value of `$typecsset-base-line-height`. 87 | 88 | ### `$typecsset-magic-number` 89 | 90 | This is a library setting, and cannot/should not be modified. Your _magic 91 | number_—typographically speaking—is the number which underpins your vertical 92 | rhythm. This is sourced from your `$typecsset-magic-number` setting and will 93 | define the `margin`s and `line-height`s for all typographical elements. 94 | 95 | ### `$typecsset-magic-ratio` 96 | 97 | This is another library variable, and simply holds your magic number as a ratio 98 | of your chosen base font size. 99 | 100 | ## Tools 101 | 102 | Typecsset has a number of mixins and functions which are used to generate more 103 | verbose CSS around your own settings. 104 | 105 | ### `typecsset-font-size()` 106 | 107 | This mixin takes a pixel value for a font size and converts it into a 108 | rem-with-pixel-fallback `font-size`, with a unitless `line-height` based upon 109 | your vertical rhythm. Clever stuff! 110 | 111 | **Input:** 112 | 113 | ```scss 114 | $typecsset-base-font-size: 16px; 115 | $typecsset-base-line-height: 24px; 116 | 117 | [...] 118 | 119 | .foo { 120 | @include typecsset-font-size(20px); 121 | } 122 | ``` 123 | 124 | **Output:** 125 | ```css 126 | .foo { 127 | font-size: 20px; 128 | font-size: 1.25rem; 129 | line-height: 1.2; 130 | } 131 | ``` 132 | 133 | * `font-size: 20px;`: A pixel fallback simply lifted straight from the input 134 | into the mixin. 135 | * `font-size: 1.25rem;` A rem-based font-size for supporting browsers. This is 136 | calculated by _desired font-size_ / _base font-size_ = _font-size in rems_. 137 | 20 / 16 = 1.25. 138 | * `line-height: 1.2;`: This is a unitless value greater than 1 which, when 139 | multiplied by the element’s font-size, yields a number that is a multiple of 140 | your base line-height. It is this which keeps everything on your baseline. 141 | 1.2 * 20 = 24px. 142 | 143 | ### `typecsset-space()` 144 | 145 | The `typecsset-space()` mixin simply drops a double amount of ‘spacing’ onto a given 146 | property, e.g. `padding`: 147 | 148 | **Input:** 149 | 150 | ```scss 151 | $typecsset-base-line-height: 24px; 152 | 153 | .foo { 154 | @include typecsset-space(margin-bottom); 155 | } 156 | ``` 157 | 158 | **Output:** 159 | 160 | ```css 161 | .foo { 162 | margin-bottom: 48px; 163 | margin-bottom: 3rem; 164 | } 165 | ``` 166 | 167 | This simple-looking mixin just DRYs out some repeated Typecsset functionality. 168 | 169 | ### `typecsset-strip-units()` 170 | 171 | The `typecsset-strip-units()` function simply does as it says: it removes the 172 | units from a value that is passed into it: 173 | 174 | **Input:** 175 | 176 | ```scss 177 | .foo { 178 | line-height: typecsset-strip-units(1.5px); 179 | } 180 | ``` 181 | 182 | **Output:** 183 | 184 | ```css 185 | .foo { 186 | line-height: 1.5; 187 | } 188 | ``` 189 | 190 | This very useful function only gets used once—to get us our baseline grid image: 191 | 192 | ```scss 193 | [...] 194 | 195 | $typecsset-baseline-size: typecsset-strip-units($typecsset-magic-number); 196 | 197 | background-image: url(http://basehold.it/i/#{$typecsset-baseline-size}); /* [3] */ 198 | 199 | [...] 200 | ``` 201 | -------------------------------------------------------------------------------- /typecsset.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * Typecsset 3 | * 4 | * Typecsset is a small, unopinionated library for creating beautifully set type 5 | * on the web. Typecsset gives perfect vertical rhythm at any configurable font 6 | * size, as well as many other typographical niceties. 7 | */ 8 | 9 | 10 | 11 | 12 | 13 | //------------------------------------\\ 14 | // SETTINGS 15 | //------------------------------------\\ 16 | // Typecsset needs some variables setting before it can get started. Some of 17 | // these variables can be overriden by developers, others need to remain 18 | // untouched because Typecsset will assign them automatically based on what 19 | // you’ve told it. 20 | 21 | // What would you like your base font-size to be? Define in pixels; the library 22 | // will convert measurements to the most appropriate units (rems or unitless). 23 | $typecsset-base-font-size: 16px !default; 24 | $typecsset-base-line-height: 24px !default; 25 | 26 | // Heading sizes 27 | $typecsset-h1-size: 48px !default; 28 | $typecsset-h2-size: 36px !default; 29 | $typecsset-h3-size: 30px !default; 30 | $typecsset-h4-size: 24px !default; 31 | $typecsset-h5-size: 20px !default; 32 | $typecsset-h6-size: 18px !default; 33 | 34 | // Would you like indented (rather than spaced) paragraph delimiting? 35 | $typecsset-indented-paragraphs: false !default; 36 | 37 | // Would you like to show a baseline grid? This is handy during development. 38 | $typecsset-show-baseline: false !default; 39 | 40 | // Do not modify these variables; they are internal settings upon which the 41 | // library depends. 42 | $typecsset-magic-number: $typecsset-base-line-height; 43 | $typecsset-magic-ratio: $typecsset-base-line-height / $typecsset-base-font-size; 44 | 45 | 46 | 47 | 48 | 49 | //------------------------------------\\ 50 | // TOOLS 51 | //------------------------------------\\ 52 | // Typecsset has a number of its own tools which it uses to generate its CSS 53 | // more efficiently. 54 | 55 | // Quickly generate a font-size in rems, with a pixel fallback, based on the 56 | // value we pass into the mixin, e.g.: 57 | // 58 | // h1 { 59 | // @include typecsset-font-size(24px); 60 | // } 61 | // 62 | @mixin typecsset-font-size($font-size, $line-height: true) { 63 | font-size: $font-size; 64 | font-size: ($font-size / $typecsset-base-font-size) * 1rem; 65 | 66 | @if $line-height == true { 67 | line-height: ceil($font-size / $typecsset-base-line-height) * ($typecsset-base-line-height / $font-size); 68 | } 69 | 70 | } 71 | 72 | // Space elements by an amount based on your magic number. Pass in the property 73 | // to be indented as a paramater, e.g.: 74 | // 75 | // pre { 76 | // @include typecsset-space(padding-left); 77 | // } 78 | // 79 | @mixin typecsset-space($property) { 80 | #{$property}: 2 * $typecsset-magic-number; 81 | #{$property}: 2 * $typecsset-magic-ratio + rem; 82 | } 83 | 84 | // A small, internally-used function to remove the units from a given value. 85 | @function typecsset-strip-units($number) { 86 | @return $number / ($number * 0 + 1); 87 | } 88 | 89 | 90 | 91 | 92 | 93 | /*------------------------------------*\ 94 | #SHARED 95 | \*------------------------------------*/ 96 | /** 97 | * A lot of elements in Typecsset need to share some declarations (mainly for 98 | * vertical rhythm), so we `@extend` some silent classes. 99 | */ 100 | %typecsset-reset { 101 | margin: 0; 102 | padding: 0; 103 | } 104 | 105 | %typecsset-vertical-rhythm { 106 | @extend %typecsset-reset; 107 | margin-bottom: $typecsset-magic-number; 108 | margin-bottom: $typecsset-magic-ratio + rem; 109 | } 110 | 111 | 112 | 113 | 114 | 115 | /*------------------------------------*\ 116 | #BASE 117 | \*------------------------------------*/ 118 | /** 119 | * 1. Set the base element’s `font-size` to the value of your choosing. Set in 120 | * ems, assuming a browser default of 16px. 121 | * 2. Work out the unitless `line-height` for your project based around your 122 | * desired `line-height` (defined previously in pixels), and your project’s 123 | * base font size. 124 | */ 125 | 126 | @if $typecsset-show-baseline == true { 127 | /** 128 | * 3. If you have chosen to display a baseline grid, we turn it on here. 129 | */ 130 | } 131 | 132 | html { 133 | font-size: $typecsset-base-font-size / 16px + em; /* [1] */ 134 | line-height: $typecsset-base-line-height / $typecsset-base-font-size; /* [2] */ 135 | 136 | // If you have chosen to display a baseline grid, we turn it on here. 137 | @if $typecsset-show-baseline == true { 138 | 139 | $typecsset-baseline-size: typecsset-strip-units($typecsset-magic-number); 140 | 141 | background-image: url(http://basehold.it/i/#{$typecsset-baseline-size}); /* [3] */ 142 | } 143 | 144 | } 145 | 146 | body { 147 | margin: 0; 148 | } 149 | 150 | 151 | 152 | 153 | 154 | /*------------------------------------*\ 155 | #HEADINGS 156 | \*------------------------------------*/ 157 | h1 { 158 | @extend %typecsset-vertical-rhythm; 159 | @include typecsset-font-size($typecsset-h1-size); 160 | } 161 | 162 | h2 { 163 | @extend %typecsset-vertical-rhythm; 164 | @include typecsset-font-size($typecsset-h2-size); 165 | } 166 | 167 | h3 { 168 | @extend %typecsset-vertical-rhythm; 169 | @include typecsset-font-size($typecsset-h3-size); 170 | } 171 | 172 | h4 { 173 | @extend %typecsset-vertical-rhythm; 174 | @include typecsset-font-size($typecsset-h4-size); 175 | } 176 | 177 | h5 { 178 | @extend %typecsset-vertical-rhythm; 179 | @include typecsset-font-size($typecsset-h5-size); 180 | } 181 | 182 | h6 { 183 | @extend %typecsset-vertical-rhythm; 184 | @include typecsset-font-size($typecsset-h6-size); 185 | } 186 | 187 | 188 | 189 | 190 | 191 | /*------------------------------------*\ 192 | #LISTS 193 | \*------------------------------------*/ 194 | ul, ol, dd { 195 | @extend %typecsset-vertical-rhythm; 196 | @include typecsset-space(margin-left); 197 | } 198 | 199 | li > ul, 200 | li > ol { 201 | margin-bottom: 0; 202 | } 203 | 204 | 205 | 206 | 207 | 208 | /*------------------------------------*\ 209 | #PARAGRAPHS 210 | \*------------------------------------*/ 211 | p { 212 | @extend %typecsset-vertical-rhythm; 213 | 214 | @if $typecsset-indented-paragraphs == true { 215 | 216 | + p { 217 | @include typecsset-space(text-indent); 218 | margin-top: -$typecsset-magic-number; 219 | margin-top: -$typecsset-magic-ratio + rem; 220 | } 221 | 222 | } 223 | 224 | } 225 | 226 | /** 227 | * Not strictly a paragraph, but probably doesn’t need its own section. 228 | */ 229 | address { 230 | @extend %typecsset-vertical-rhythm; 231 | } 232 | 233 | 234 | 235 | 236 | 237 | /*------------------------------------*\ 238 | #CODE 239 | \*------------------------------------*/ 240 | pre { 241 | @extend %typecsset-vertical-rhythm; 242 | } 243 | 244 | /** 245 | * 1. Fix an odd quirk whereby, without this, code blocks are rendered at a 246 | * font-size smaller than 1em. 247 | */ 248 | code, 249 | kbd, 250 | pre, 251 | samp { 252 | font-family: monospace, monospace; /* [1] */ 253 | } 254 | 255 | 256 | 257 | 258 | 259 | /*------------------------------------*\ 260 | #QUOTES 261 | \*------------------------------------*/ 262 | /** 263 | * 1. Hang the opening quote of the blockquote. 264 | */ 265 | blockquote { 266 | text-indent: -0.41em; /* [1] */ 267 | } 268 | 269 | /** 270 | * Set up quote marks on quoting elements. This is very English-based, so we are 271 | * using “, ”, ‘, and ’ quotes. 272 | */ 273 | blockquote { 274 | @extend %typecsset-vertical-rhythm; 275 | quotes: "“" "”"; 276 | @include typecsset-space(margin-left); 277 | 278 | p { 279 | 280 | &:before { 281 | content: "“"; 282 | content: open-quote; 283 | } 284 | 285 | &:after { 286 | content: ""; 287 | content: no-close-quote; 288 | } 289 | 290 | &:last-of-type:after { 291 | content: "”"; 292 | content: close-quote; 293 | } 294 | 295 | } 296 | 297 | } 298 | 299 | q { 300 | quotes: "‘" "’" "“" "”"; 301 | 302 | &:before { 303 | content: "‘"; 304 | content: open-quote; 305 | } 306 | 307 | &:after { 308 | content: "’"; 309 | content: close-quote; 310 | } 311 | 312 | q:before { 313 | content: "“"; 314 | content: open-quote; 315 | } 316 | 317 | q:after{ 318 | content: "”"; 319 | content: close-quote; 320 | } 321 | 322 | /** 323 | * If an element opens with an inline quote, let’s hang that. 324 | */ 325 | &:first-child { 326 | display: inline-block; 327 | text-indent: -0.22em; 328 | } 329 | 330 | } 331 | 332 | 333 | 334 | 335 | 336 | /*------------------------------------*\ 337 | #TABLES 338 | \*------------------------------------*/ 339 | /** 340 | * Crude table styles; tables are very difficult to keep on the baseline. 341 | */ 342 | table { 343 | @extend %typecsset-vertical-rhythm; 344 | width: 100%; 345 | border-collapse: collapse; 346 | border-spacing: 0; 347 | } 348 | 349 | th, 350 | td { 351 | padding: $typecsset-base-line-height / 2; 352 | } 353 | --------------------------------------------------------------------------------