{"rowid": 216, "title": "Styling Components - Typed CSS With Stylable", "contents": "There\u2019s been a lot of debate recently about how best to style components for web apps so that styles don\u2019t accidentally \u2018leak\u2019 out of the component they\u2019re meant for, or clash with other styles on the page.\nElaborate CSS conventions have sprung up, such as OOCSS, SMACSS, BEM, ITCSS, and ECSS. These work well, but they are methodologies, and require everyone in the team to know them and follow them, which can be a difficult undertaking across large or distributed teams.\nOthers just give up on CSS and put all their styles in JavaScript. Now, I\u2019m not bashing JS, especially so close to its 22nd birthday, but CSS-in-JS has problems of its own. Browsers have 20 years experience in optimising their CSS engines, so JavaScript won\u2019t be as fast as using real CSS, and in any case, this requires waiting for JS to download, parse, execute then render the styles.\nThere\u2019s another problem with CSS-in-JS, too. Since Responsive Web Design hit the streets, most designers no longer make comps in Photoshop or its equivalents; instead, they write CSS. Why hire an expensive design professional and require them to learn a new way of doing their job? \nA recent thread on Twitter asked \u201cWhat\u2019s your biggest gripe with CSS-in-JS?\u201d, and the replies were illuminating: \u201cAlways having to remember to camelCase properties then spending 10min pulling hair out when you do forget\u201d, \u201cthe cryptic domain-specific languages that each of the frameworks do just ever so slightly differently\u201d, \u201cWhen I test look and feel in browser, then I copy paste from inspector, only to have to re-write it as a JSON object\u201d, \u201cLack of linting, autocomplete, and css plug-ins for colors/ incrementing/ etc\u201d. \nIf you\u2019re a developer, and you\u2019re still unconvinced, I challenge you to let designers change the font in your IDE to Zapf Chancery and choose a new colour scheme, simply because they like it better. Does that sound like fun? Will that boost your productivity? Thought not.\nSome chums at Wix Engineering and I wanted to see if we could square this circle. Wix-hosted sites have always used CSS-in-JS (the concept isn\u2019t new; it was in Netscape 4!) but that was causing performance problems. Could we somehow devise a method of extending CSS (like SASS and LESS do) that gives us styles that are guaranteed not to leak or clash, that is compatible with code editors\u2019 autocompletion, and which could be pre-processed at build time to valid, cross-browser, static CSS?\nAfter a few months and a few proofs of concept later (drumroll), yes \u2013 we could! We call it Stylable.\nIntroducing Stylable\nStylable is a CSS pre-processor, like SASS or LESS. It uses CSS syntax so all your development tools will work. At build time, the Stylable CSS extensions are transpiled to flat, valid, cross-browser vanilla CSS for maximum performance. There\u2019s quite a bit to it, and this is a short article, so let\u2019s look at the basic concepts.\nComponents all the way down\nStylable is designed for component-based systems. Imagine you have a Gallery component. Within that, there is a Navigation component (for example, containing a \u2018next\u2019, \u2018previous\u2019, \u2018show all thumbnails\u2019, and \u2018show all albums\u2019 controls), and within that there are NavButton components. Each component is discrete, used elsewhere in the system in different contexts, perhaps maintained by different team members or even different organisations \u2014 you can use Stylable to add a typed interface to non-Stylable component libraries, as well as using it to build an app from scratch.\nFirstly, Stylable will automatically namespace styles so they only apply inside that component, by rewriting them at build time with a unique (but human-readable) prefix. So, for example,\n
might be re-written as
. \nSo far, so BEM-like (albeit without the headache of remembering a convention). But what else can it do?\nCustom pseudo-elements\nAn important feature of Stylable is the ability to reach into a component and style it from the outside, without having to know about its internal structure. Let\u2019s see the guts of a simple JSX button component in the file button.jsx:\nrender () {\n return (\n \n );\n}\n(Note:className is the JSX way of setting a class on an element; this example uses React, but Stylable itself is framework-agnostic.)\nI style it using a Stylable stylesheet (the .st.css suffix tells the preprocessor to process this file):\n/* button.st.css */\n\n/* note that the root class is automatically placed on the root HTML \nelement by Stylable React integration */\n.root {\n background: #b0e0e6;\n}\n\n.icon {\n display: block; \n height: 2em;\n background-image: url('./assets/btnIcon.svg');\n}\n\n.label {\n font-size: 1.2em;\n color: rgba(81, 12, 68, 1.0);\n}\nNote that Stylable allows all the CSS that you know and love to be included. As Drew Powers wrote in his review:\n\nwith Stylable, you get CSS, and every part of CSS. This seems like a \u201cduh\u201d observation, but this is significant if you\u2019ve ever battled with a CSS-in-JS framework over a lost or \u201chacky\u201d implementation of a basic CSS feature.\n\nI can import my Button component into another component - this time, panel.jsx:\n/* panel.jsx */\nimport * as React from 'react';\nimport {properties, stylable} from 'wix-react-tools';\nimport {Button} from '../button';\nimport style from './panel.st.css';\n\nexport const Panel = stylable(style)(() => (\n
\n
\n));\nIn panel.st.css: \n/* panel.st.css */\n:import {\n -st-from: './button.st.css';\n -st-default: Button;\n}\n\n/* cancelBtn is of type Button */\n.cancelBtn {\n -st-extends: Button;\n background: cornflowerblue;\n}\n\n/* targets the label of