├── .gitignore ├── .projections.json ├── CONTRIBUTING.md ├── Dockerfile-dev ├── Gemfile ├── Gemfile.lock ├── Makefile ├── README.md ├── _authors └── rstacruz.md ├── _config.yml ├── _drafts └── styled-jsx-is-awesome.md ├── _includes ├── about-the-site.html ├── base.html ├── body.html ├── end.html ├── head.html ├── meta.html ├── next-article.html ├── polyfills.html ├── post.html ├── site-header.html └── social-list.html ├── _layouts ├── article.html └── landing.html ├── _posts ├── 2013-01-07-easy-favicons.md ├── 2013-11-27-get-started-with-ansible.md ├── 2015-02-13-get-started-with-mocha.md ├── 2015-02-14-use-browserify-to-precompile.md ├── 2015-02-15-javascript-orms-suck.md ├── 2015-02-16-extend-sucks.md ├── 2015-02-17-node-js-exiting.md ├── 2015-02-18-rails-inline-partials.md ├── 2015-02-19-use-markdown-documentation.md ├── 2015-02-23-use-bower-in-npm.md ├── 2015-02-24-refactoring-long-calls.md ├── 2015-02-24-using-bower-and-rails-in-heroku.md ├── 2015-02-25-es6-class-pitfalls.md ├── 2015-02-26-organizing-js.md ├── 2015-03-02-inline-svg-in-css.md ├── 2015-03-03-easy-color-computations.md ├── 2015-03-05-css-ligatures.md ├── 2015-03-06-mocha-clean.md ├── 2015-03-09-releasing-packages.md ├── 2015-03-10-static-sites-in-heroku.md ├── 2015-03-13-relative-paths-in-jekyll.md ├── 2015-03-20-javascript-shortcuts.md ├── 2015-03-27-github-two-factor-authentication.md ├── 2015-04-14-use-macvim-with-lua.md ├── 2015-04-17-ie-polyfills.md ├── 2015-04-20-osx-keyboard-shortcuts.md ├── 2015-04-22-navigate-code-with-ctags.md ├── 2015-05-18-local-google-fonts.md ├── 2015-05-19-iojs-on-homebrew.md ├── 2015-05-24-repeat-tmux-from-vim.md ├── 2015-05-25-markdown-in-jekyll.md ├── 2015-05-26-babel-ie-class-inheritance.md ├── 2015-05-29-testing-static-sites.md ├── 2015-06-06-alfred-color-schemes.md ├── 2015-06-22-use-vendor-bundle.md ├── 2015-07-06-mocha-instanbul-coverage.md ├── 2015-11-17-pausing-capybara-selenium.md ├── 2015-11-23-parallel-npm-commands.md ├── 2015-11-28-factory_girl_with_custom_factories.md ├── 2015-12-10-using-git-merge-base.md ├── 2015-12-17-rails-and-cloudfront.md ├── 2016-01-02-selective-polyfilling.md ├── 2016-01-21-npm-in-rails.md ├── 2016-08-11-ordered-keys-in-js.md ├── 2016-08-25-my-immutable-toolkit.md ├── 2016-08-28-filtering-falsy-values.md ├── 2016-09-29-neovim-with-python-on-osx.md ├── 2016-12-28-graphql-on-javascript.md ├── 2017-02-19-life-in-side-quests.md ├── 2017-03-14-redux-side-effects.md ├── 2017-06-06-rails-mailer-race-conditions.md ├── 2017-07-12-less-cpu-on-development.md ├── 2017-09-19-a-better-hello-world.md ├── 2018-05-22-css-in-js-showdown-draft.md └── 2018-06-09-github-always-ssh.md ├── _sass ├── base │ ├── normalize.scss │ ├── typography.sass │ └── utils.sass ├── components │ ├── about-the-site.sass │ ├── big-button.sass │ ├── brief-intro.sass │ ├── full-image.sass │ ├── hint.sass │ ├── hljs.sass │ ├── next-article.sass │ ├── post-headline.sass │ ├── post-icon.sass │ ├── post-index.sass │ ├── post-list.sass │ ├── site-header.sass │ └── social-list.sass ├── elements │ ├── body.sass │ ├── code.sass │ └── table.sass ├── helpers │ ├── blink.sass │ ├── general.sass │ └── margins.sass └── style.sass ├── _trash ├── 2015-05-20-rails-i18n-best-practices.md ├── 2015-06-04-rscss-alternate-naming.md ├── aoeu.md ├── clean-up-commands-in-shell-scripts.md ├── creating-streams.md ├── how-js-testing-works.md ├── traversee-du-desert.md └── unite.md ├── assets ├── bg │ ├── Makefile │ ├── pebbles.jpg │ ├── rosebench.jpg │ ├── roughwall.jpg │ ├── stairs.jpg │ └── woodfloor.jpg ├── script.js └── style.sass ├── atom.xml ├── docker-compose.yml ├── images ├── alfred-dark.png ├── cloudfront-reference.png ├── iojs-linking.png ├── keep-missions.png ├── ligatures.png ├── mocha-istanbul.png ├── office-fonts.png ├── osx-keyboard.png ├── side-quest-example.jpg ├── skyfonts.png ├── tmux-repeat.gif └── unite-ctags.png ├── index.html └── reference ├── authors.md ├── code.md ├── general.md ├── images.md ├── index.md └── tables.md /.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | .jekyll-metadata 3 | node_modules 4 | -------------------------------------------------------------------------------- /.projections.json: -------------------------------------------------------------------------------- 1 | { 2 | "_posts/*.md": { 3 | "type": "post", 4 | "template": [ 5 | "---", 6 | "title: {basename}", 7 | "tags: [Development]", 8 | "description: ...", 9 | "---" 10 | ] 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Developer notes 2 | 3 | ## Docker setup 4 | 5 | ```bash 6 | alias dr='docker-compose run --rm web' 7 | 8 | # Build image 9 | docker-compose build 10 | 11 | # First-time setup 12 | dr bundle install 13 | ``` 14 | 15 | Server: 16 | 17 | ```bash 18 | # Start server 19 | docker-compose up 20 | ``` 21 | 22 | Tests: 23 | 24 | ```bash 25 | echo "lol, you wish" 26 | ``` 27 | -------------------------------------------------------------------------------- /Dockerfile-dev: -------------------------------------------------------------------------------- 1 | FROM ruby:2.5 2 | RUN mkdir -p /app 3 | WORKDIR /app 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # http://jekyllrb.com/docs/github-pages/ 2 | source 'https://rubygems.org' 3 | 4 | gem 'github-pages' 5 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activesupport (4.2.9) 5 | i18n (~> 0.7) 6 | minitest (~> 5.1) 7 | thread_safe (~> 0.3, >= 0.3.4) 8 | tzinfo (~> 1.1) 9 | addressable (2.5.2) 10 | public_suffix (>= 2.0.2, < 4.0) 11 | coffee-script (2.4.1) 12 | coffee-script-source 13 | execjs 14 | coffee-script-source (1.11.1) 15 | colorator (1.1.0) 16 | commonmarker (0.17.9) 17 | ruby-enum (~> 0.5) 18 | concurrent-ruby (1.0.5) 19 | dnsruby (1.60.2) 20 | em-websocket (0.5.1) 21 | eventmachine (>= 0.12.9) 22 | http_parser.rb (~> 0.6.0) 23 | ethon (0.11.0) 24 | ffi (>= 1.3.0) 25 | eventmachine (1.2.7) 26 | execjs (2.7.0) 27 | faraday (0.15.1) 28 | multipart-post (>= 1.2, < 3) 29 | ffi (1.9.23) 30 | forwardable-extended (2.6.0) 31 | gemoji (3.0.0) 32 | github-pages (185) 33 | activesupport (= 4.2.9) 34 | github-pages-health-check (= 1.8.1) 35 | jekyll (= 3.7.3) 36 | jekyll-avatar (= 0.5.0) 37 | jekyll-coffeescript (= 1.1.1) 38 | jekyll-commonmark-ghpages (= 0.1.5) 39 | jekyll-default-layout (= 0.1.4) 40 | jekyll-feed (= 0.9.3) 41 | jekyll-gist (= 1.5.0) 42 | jekyll-github-metadata (= 2.9.4) 43 | jekyll-mentions (= 1.3.0) 44 | jekyll-optional-front-matter (= 0.3.0) 45 | jekyll-paginate (= 1.1.0) 46 | jekyll-readme-index (= 0.2.0) 47 | jekyll-redirect-from (= 0.13.0) 48 | jekyll-relative-links (= 0.5.3) 49 | jekyll-remote-theme (= 0.3.1) 50 | jekyll-sass-converter (= 1.5.2) 51 | jekyll-seo-tag (= 2.4.0) 52 | jekyll-sitemap (= 1.2.0) 53 | jekyll-swiss (= 0.4.0) 54 | jekyll-theme-architect (= 0.1.1) 55 | jekyll-theme-cayman (= 0.1.1) 56 | jekyll-theme-dinky (= 0.1.1) 57 | jekyll-theme-hacker (= 0.1.1) 58 | jekyll-theme-leap-day (= 0.1.1) 59 | jekyll-theme-merlot (= 0.1.1) 60 | jekyll-theme-midnight (= 0.1.1) 61 | jekyll-theme-minimal (= 0.1.1) 62 | jekyll-theme-modernist (= 0.1.1) 63 | jekyll-theme-primer (= 0.5.3) 64 | jekyll-theme-slate (= 0.1.1) 65 | jekyll-theme-tactile (= 0.1.1) 66 | jekyll-theme-time-machine (= 0.1.1) 67 | jekyll-titles-from-headings (= 0.5.1) 68 | jemoji (= 0.9.0) 69 | kramdown (= 1.16.2) 70 | liquid (= 4.0.0) 71 | listen (= 3.1.5) 72 | mercenary (~> 0.3) 73 | minima (= 2.4.1) 74 | nokogiri (>= 1.8.1, < 2.0) 75 | rouge (= 2.2.1) 76 | terminal-table (~> 1.4) 77 | github-pages-health-check (1.8.1) 78 | addressable (~> 2.3) 79 | dnsruby (~> 1.60) 80 | octokit (~> 4.0) 81 | public_suffix (~> 2.0) 82 | typhoeus (~> 1.3) 83 | html-pipeline (2.8.0) 84 | activesupport (>= 2) 85 | nokogiri (>= 1.4) 86 | http_parser.rb (0.6.0) 87 | i18n (0.9.5) 88 | concurrent-ruby (~> 1.0) 89 | jekyll (3.7.3) 90 | addressable (~> 2.4) 91 | colorator (~> 1.0) 92 | em-websocket (~> 0.5) 93 | i18n (~> 0.7) 94 | jekyll-sass-converter (~> 1.0) 95 | jekyll-watch (~> 2.0) 96 | kramdown (~> 1.14) 97 | liquid (~> 4.0) 98 | mercenary (~> 0.3.3) 99 | pathutil (~> 0.9) 100 | rouge (>= 1.7, < 4) 101 | safe_yaml (~> 1.0) 102 | jekyll-avatar (0.5.0) 103 | jekyll (~> 3.0) 104 | jekyll-coffeescript (1.1.1) 105 | coffee-script (~> 2.2) 106 | coffee-script-source (~> 1.11.1) 107 | jekyll-commonmark (1.2.0) 108 | commonmarker (~> 0.14) 109 | jekyll (>= 3.0, < 4.0) 110 | jekyll-commonmark-ghpages (0.1.5) 111 | commonmarker (~> 0.17.6) 112 | jekyll-commonmark (~> 1) 113 | rouge (~> 2) 114 | jekyll-default-layout (0.1.4) 115 | jekyll (~> 3.0) 116 | jekyll-feed (0.9.3) 117 | jekyll (~> 3.3) 118 | jekyll-gist (1.5.0) 119 | octokit (~> 4.2) 120 | jekyll-github-metadata (2.9.4) 121 | jekyll (~> 3.1) 122 | octokit (~> 4.0, != 4.4.0) 123 | jekyll-mentions (1.3.0) 124 | activesupport (~> 4.0) 125 | html-pipeline (~> 2.3) 126 | jekyll (~> 3.0) 127 | jekyll-optional-front-matter (0.3.0) 128 | jekyll (~> 3.0) 129 | jekyll-paginate (1.1.0) 130 | jekyll-readme-index (0.2.0) 131 | jekyll (~> 3.0) 132 | jekyll-redirect-from (0.13.0) 133 | jekyll (~> 3.3) 134 | jekyll-relative-links (0.5.3) 135 | jekyll (~> 3.3) 136 | jekyll-remote-theme (0.3.1) 137 | jekyll (~> 3.5) 138 | rubyzip (>= 1.2.1, < 3.0) 139 | jekyll-sass-converter (1.5.2) 140 | sass (~> 3.4) 141 | jekyll-seo-tag (2.4.0) 142 | jekyll (~> 3.3) 143 | jekyll-sitemap (1.2.0) 144 | jekyll (~> 3.3) 145 | jekyll-swiss (0.4.0) 146 | jekyll-theme-architect (0.1.1) 147 | jekyll (~> 3.5) 148 | jekyll-seo-tag (~> 2.0) 149 | jekyll-theme-cayman (0.1.1) 150 | jekyll (~> 3.5) 151 | jekyll-seo-tag (~> 2.0) 152 | jekyll-theme-dinky (0.1.1) 153 | jekyll (~> 3.5) 154 | jekyll-seo-tag (~> 2.0) 155 | jekyll-theme-hacker (0.1.1) 156 | jekyll (~> 3.5) 157 | jekyll-seo-tag (~> 2.0) 158 | jekyll-theme-leap-day (0.1.1) 159 | jekyll (~> 3.5) 160 | jekyll-seo-tag (~> 2.0) 161 | jekyll-theme-merlot (0.1.1) 162 | jekyll (~> 3.5) 163 | jekyll-seo-tag (~> 2.0) 164 | jekyll-theme-midnight (0.1.1) 165 | jekyll (~> 3.5) 166 | jekyll-seo-tag (~> 2.0) 167 | jekyll-theme-minimal (0.1.1) 168 | jekyll (~> 3.5) 169 | jekyll-seo-tag (~> 2.0) 170 | jekyll-theme-modernist (0.1.1) 171 | jekyll (~> 3.5) 172 | jekyll-seo-tag (~> 2.0) 173 | jekyll-theme-primer (0.5.3) 174 | jekyll (~> 3.5) 175 | jekyll-github-metadata (~> 2.9) 176 | jekyll-seo-tag (~> 2.0) 177 | jekyll-theme-slate (0.1.1) 178 | jekyll (~> 3.5) 179 | jekyll-seo-tag (~> 2.0) 180 | jekyll-theme-tactile (0.1.1) 181 | jekyll (~> 3.5) 182 | jekyll-seo-tag (~> 2.0) 183 | jekyll-theme-time-machine (0.1.1) 184 | jekyll (~> 3.5) 185 | jekyll-seo-tag (~> 2.0) 186 | jekyll-titles-from-headings (0.5.1) 187 | jekyll (~> 3.3) 188 | jekyll-watch (2.0.0) 189 | listen (~> 3.0) 190 | jemoji (0.9.0) 191 | activesupport (~> 4.0, >= 4.2.9) 192 | gemoji (~> 3.0) 193 | html-pipeline (~> 2.2) 194 | jekyll (~> 3.0) 195 | kramdown (1.16.2) 196 | liquid (4.0.0) 197 | listen (3.1.5) 198 | rb-fsevent (~> 0.9, >= 0.9.4) 199 | rb-inotify (~> 0.9, >= 0.9.7) 200 | ruby_dep (~> 1.2) 201 | mercenary (0.3.6) 202 | mini_portile2 (2.3.0) 203 | minima (2.4.1) 204 | jekyll (~> 3.5) 205 | jekyll-feed (~> 0.9) 206 | jekyll-seo-tag (~> 2.1) 207 | minitest (5.11.3) 208 | multipart-post (2.0.0) 209 | nokogiri (1.8.2) 210 | mini_portile2 (~> 2.3.0) 211 | octokit (4.9.0) 212 | sawyer (~> 0.8.0, >= 0.5.3) 213 | pathutil (0.16.1) 214 | forwardable-extended (~> 2.6) 215 | public_suffix (2.0.5) 216 | rb-fsevent (0.10.3) 217 | rb-inotify (0.9.10) 218 | ffi (>= 0.5.0, < 2) 219 | rouge (2.2.1) 220 | ruby-enum (0.7.2) 221 | i18n 222 | ruby_dep (1.5.0) 223 | rubyzip (1.2.1) 224 | safe_yaml (1.0.4) 225 | sass (3.5.6) 226 | sass-listen (~> 4.0.0) 227 | sass-listen (4.0.0) 228 | rb-fsevent (~> 0.9, >= 0.9.4) 229 | rb-inotify (~> 0.9, >= 0.9.7) 230 | sawyer (0.8.1) 231 | addressable (>= 2.3.5, < 2.6) 232 | faraday (~> 0.8, < 1.0) 233 | terminal-table (1.8.0) 234 | unicode-display_width (~> 1.1, >= 1.1.1) 235 | thread_safe (0.3.6) 236 | typhoeus (1.3.0) 237 | ethon (>= 0.9.0) 238 | tzinfo (1.2.5) 239 | thread_safe (~> 0.1) 240 | unicode-display_width (1.3.2) 241 | 242 | PLATFORMS 243 | ruby 244 | 245 | DEPENDENCIES 246 | github-pages 247 | 248 | BUNDLED WITH 249 | 1.16.1 250 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PORT ?= 3000 2 | bundle := bundle 3 | 4 | start: bundle 5 | ${bundle} exec jekyll serve --safe --watch --port ${PORT} 6 | 7 | # Incremental building is faster, but more fragile 8 | start-incremental: bundle 9 | ${bundle} exec jekyll serve --safe --drafts --watch --incremental --port ${PORT} 10 | 11 | build: bundle 12 | ${bundle} exec jekyll build 13 | 14 | bundle: 15 | ${bundle} 16 | 17 | # Print tags 18 | tags: 19 | grep "tags:" _posts/*.md -h | sort | uniq 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > **Archived** — Thank you for staying tuned with my blog! A new version of the blog is avialable at [**rstacruz/til**](https://github.com/rstacruz/til) _(github.com)_. 2 | 3 | --- 4 | 5 | # Today I learned 6 | 7 | *Grab bag of random things I pick up.* Got comments? Suggestions? Corrections? [I'd love to hear from you.](https://github.com/rstacruz/til/issues) 8 | 9 | ## Development 10 | 11 | Local server: 12 | 13 | make 14 | PORT=4000 make 15 | 16 | Deployment: 17 | 18 | git push 19 | 20 | ## Thanks 21 | 22 | © 2013+ Rico Sta. Cruz, licensed [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/) 23 | -------------------------------------------------------------------------------- /_authors/rstacruz.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Rico Sta. Cruz 3 | ogp: https://www.facebook.com/ricostacruz 4 | twitter: rstacruz 5 | --- 6 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | # Markdown 2 | markdown: kramdown 3 | kramdown: 4 | input: GFM 5 | hard_wrap: false 6 | 7 | # Site settings 8 | permalink: /:title.html 9 | exclude: 10 | - "Makefile" 11 | - "README.md" 12 | - "CONTRIBUTING.md" 13 | - "CNAME" 14 | - "node_modules" 15 | - "vendor" 16 | - "Gemfile" 17 | - "Gemfile.lock" 18 | - "docker-compose.yml" 19 | - "Dockerfile-dev" 20 | sass: 21 | style: compressed 22 | 23 | # Site info 24 | url: https://ricostacruz.com/til 25 | title: Today I Learned 26 | 27 | # Google analytics 28 | analytics: 29 | hostname: ricostacruz.com 30 | id: "UA-20473929-1" 31 | 32 | # Collections 33 | collections: 34 | - authors 35 | 36 | # Default variables 37 | defaults: 38 | - 39 | scope: 40 | path: "" 41 | values: 42 | layout: "article" 43 | tags: [] 44 | secret: false 45 | author: Rico Sta. Cruz 46 | -------------------------------------------------------------------------------- /_drafts/styled-jsx-is-awesome.md: -------------------------------------------------------------------------------- 1 | # CSS-in-JavaScript 2 | 3 | [styled-jsx] has been my preferred way of integrating CSS in JavaScript. It lets me write CSS in a more declarative fashion. It leads to code that's easier to understand. 4 | 5 | Before I tell you why I prefer _styled-jsx_, let's learn about some programming concepts—It'll all make sense later, trust me! 6 | 7 | ## Imperative vs. declarative code 8 | 9 | There are two styles of expressing data. The most common way is to simply write it out as a data structure. We can call this a **declarative** style of writing, where we try to express logic without providing any instructions. 10 | 11 | ```js 12 | { 13 | "name": "my-js-package", 14 | "description": "A sample package", 15 | "author": "Rico Sta. Cruz" 16 | } 17 | ``` 18 | 19 | There are cases when this style may not be flexible enough, so some systems take an **imperative** approach. In contrast to the declarative style, it's a piece of code with instructions that runs procedurally. Here's an example of a Ruby [gem specification](https://guides.rubygems.org/specification-reference/), which defines a Ruby package's metadata: 20 | 21 | ```rb 22 | Gem::Specification.new do |spec| 23 | spec.name = 'my-ruby-gem' 24 | spec.summary = 'A sample package' 25 | spec.authors = ['Rico Sta. Cruz'] 26 | end 27 | ``` 28 | 29 | ## But they look the same! 30 | 31 | Ruby's gem specification style is _imperative_ because we're issuing instructions that are to be ran sequentially. It can keep variables, call functions, and do all the things you can do in a Ruby program. Think of the Ruby gemspec as a program talking to the system: 32 | 33 | > - _Okay, computer. Build a new Gem specification._ 34 | > - _Set the name to 'my-ruby-gem'._ 35 | > - _Set the summary to 'A sample package'._ 36 | > - _Finish building._ 37 | 38 | On the other hand, JavaScript's _declarative_ style isn't concerned with any instructions or control flow. It's not a piece of code that talks to your system, it's really just a table of keys and values. 39 | 40 | ## Imperative is powerful 41 | 42 | Imperative style gives you the power to write expressions that you can't easily do with a declarative-style conventions. For instance, here's an example gem specification where the list of files are gathered via a system command (`git ls-files`): 43 | 44 | ```rb 45 | Gem::Specification.new do |spec| 46 | spec.name = 'my-gem' 47 | spec.summary = 'This is my gem' 48 | spec.files = `git ls-files -z`.split("\x0") 49 | end 50 | ``` 51 | 52 | ## Declarative is easier to understand 53 | 54 | Imperative conventions give developers a great amount of flexibility. However, this power comes at the cost of _complexity_. Here's an example where development dependencies are _imperatively_ defined in a Ruby gem, taking advantage of Ruby's `Array#each` to reduce redundancy. 55 | 56 | ```rb 57 | Gem::Specification.new do |spec| 58 | ['bundler', 'rake', 'minitest', 'rails'].each do |gemname| 59 | spec.add_development_dependency(gemname) 60 | end 61 | end 62 | ``` 63 | 64 | In contrast, here's how it may be _declaratively_ defined in a JavaScript package's `package.json`. 65 | 66 | ```js 67 | { 68 | "dependencies": { 69 | "react": "^16.0.0", 70 | "react-dom": "^16.0.0", 71 | "redux": "^4.0.1" 72 | } 73 | } 74 | ``` 75 | 76 | JavaScript's _declarative aproach_ may be less flexible than the _imperative_ one, but the constraints of a JSON format makes things more predictable and easier to glance. 77 | 78 | ## CSS is declarative 79 | 80 | CSS is beautifully declarative. To write CSS is to write a list of rules, not a set of instructions. For instance, we would say _buttons are supposed to be blue_, rather than _turn all buttons to blue_. 81 | 82 | ```css 83 | /* "Buttons are supposed to be blue" in CSS. */ 84 | button { 85 | background: blue; 86 | } 87 | ``` 88 | 89 | ```js 90 | // "Turn all buttons to blue" in JavaScript. 91 | // (Please don't do this.) 92 | Array.from(document.querySelectorAll('button')).forEach(button => { 93 | button.style.background = 'blue' 94 | }) 95 | ``` 96 | 97 | ## A lot of JS-in-CSS is imperative 98 | 99 | At first glance, we can say that most JS-in-CSS solutions require you to write in a declarative style, since it's mostly just taking CSS and putting it in JavaScript. Here's how you would define a blue button using [styled-components]: 100 | 101 | ```js 102 | const Button = styled.a` 103 | background: blue; 104 | ` 105 | ``` 106 | 107 | However, how would you start making red `danger` buttons? With _styled-components_, you'll have to provide a function which returns a CSS fragment depending on how you would interpret `props`: 108 | 109 | ```js 110 | // using styled-components 111 | const Button = styled.a` 112 | background: blue; 113 | 114 | ${props => 115 | props.danger && 116 | css` 117 | background: red; 118 | `}; 119 | ` 120 | ``` 121 | 122 | This is where it starts to break down. We're now mixing the declarative nature of CSS with some rules that are written in an imperative style. We're also now interweaving 2 languages together—CSS and JavaScript—where your brain may have to switch contexts mid-way. This brain-context-switching is even more apparent in some other CSS-in-JS libraries: 123 | 124 | ```css 125 | // using emotion 126 | const Button = styled.a` 127 | background: ${props => props.danger ? 'red' : 'blue'}; 128 | opacity: ${props => props.isHidden ? 0 : 1}; 129 | ` 130 | ``` 131 | 132 | ## Declarative CSS with styled-jsx 133 | 134 | [styled-jsx] lets me write CSS in a declarative fashion. It also minimizes the interweaving of CSS and JavaScript code. This, in my opinion, makes styled-jsx code easier-to-understand, even at the modest cost of a little extra verbosity. 135 | 136 | How would you style a danger button differently in _styled-jsx_? Just use CSS classes as you normally would. Simple! 137 | 138 | ```js 139 | const Button = ({ children, danger }) => { 140 | return ( 141 | 142 | {children} 143 | 144 | 145 | ) 146 | } 147 | 148 | const style = css` 149 | .button { 150 | background: blue; 151 | } 152 | 153 | .button.danger { 154 | background: red; 155 | } 156 | ` 157 | ``` 158 | 159 | [styled-components]: https://www.styled-components.com/ 160 | [styled-jsx]: https://github.com/zeit/styled-jsx 161 | [emotion]: https://emotion.sh/ 162 | -------------------------------------------------------------------------------- /_includes/about-the-site.html: -------------------------------------------------------------------------------- 1 |
4 | I'm Rico Sta. Cruz, a web developer 5 | who makes open-source JavaScript projects. You're reading my 6 | Today I learned blog. 7 | 8 | Follow me on 9 | Twitter for web development snark, 10 | GitHub for code, and 11 | Instagram for calligraphy. 12 |
13 |22 |
23 |