8 ms·
Show HN: Styled-components – Use the best of ES6 to style React apps
- Kiro 10y agoWhat about media queries?
- mxstbr 10y agoJust like any other media query, except without the selector! const AdjustsAt360px = styled.div` @media screen and (max-width: 360px) { this-is-applied-under: 360px; } `;
- hkeide 10y agoHow is this implemented? And how is the :hover pseudo class implemented? Awesome work by the way!
- mxstbr 10y agoIt isn't "implemented" – it's just CSS! Literally! (Note: Almost the sole thing we do to that CSS before injecting it into the DOM is adding a hash of the contents as the selector. Not sure if that counts as "implemented"?)
- hkeide 10y agoThank you, that's what I wanted to know, since projects like Radium implement e.g. hover in JS using onMouseEnter() etc, which sounds slow. See https://github.com/FormidableLabs/radium#how-does-radium-work https://github.com/FormidableLabs/radium#how-does-radium-wor...
- mxstbr 10y agoExactly, they use inline styles, we use CSS. :) (that's the difference between _inline styles_ (<p style={styles} />) and CSS-in-JS (<p className={styles} />) libs)
- hkeide 10y agoI don't think everyone uses that distinction, see this list for example. Radium is included among others: https://github.com/MicheleBertoli/css-in-js https://github.com/MicheleBertoli/css-in-js Or this influential talk: https://speakerdeck.com/vjeux/react-css-in-js https://speakerdeck.com/vjeux/react-css-in-js
- mxstbr 10y agoI very much realize that, which is why I've been pushing towards people recognizing this because it _does_ make a huge difference! (as seen by the OC that kicked off this discussion)
- ioseph 10y agoI'm probably missing something but what's the advantage of this over usual way of defining styles in React?
- mxstbr 10y agoWhat do you mean with "the usual way"? ;) There is vanilla CSS, Sass, CSS modules, Aphrodite, Radium, JSS,… This image from the talk I just gave about it sums the differences up quite well: http://imgur.com/dmiROz6.jpg http://imgur.com/dmiROz6.jpg You can also see a comparison with other styling methods here: https://github.com/styled-components/comparison https://github.com/styled-components/comparison (this is where the checklists are from)
- madeofpalk 10y agoInteresting. What warrants a for CSS Modules co-location? Is it just because you can't write it in the same JS file as your component? I'm also super duper skeptical of style interoperability between React Native and the browser. From experience styling in React Native suffers from the uncanny valley - its so close to browser CSS, but ends up failing in rather significant ways (mainly layout) that would prevent style reuse.
- mxstbr 10y agoYes exactly. It's less about interoperability and more about using the same styling system for_all_ parts of your application. Styling on ReactNative is different enough to have to be careful when doing it, though theoretically it's very possible.
- pluma 10y agoNote that while CSS modules doesn't provide an out-of-the-box solution for themeing you can use css variables and then either just swap out the variables (if you only target browsers that support the custom properties spec) or run the CSS through postCSS. The important difference however is that CSS-in-JS can swap out themes on the fly whereas this would be a static solution that doesn't scale e.g. if you need per-user customization.
- cel1ne 10y agoI want to mention my styling library here: https://www.npmjs.com/package/react-native-style-tachyons https://www.npmjs.com/package/react-native-style-tachyons The best part: it gives you a consistent spacing [0] and a consistent font scale [1] which is relative to rem. No more magic values, just use classes: ma0 ... ma7 margin: 0|0.25|0.5|1|2|4|8|16 rem ml|mr|mb|mt [0-7] marginLeft, marginRight, marginBottom, marginTop mh [0-7] marginHorizontal mv [0-7] marginVertical /* Same with p for padding */ No more stylesheets, everything is there at a glance and easily fixable: <View cls="bt bb jcfs pa2"> /* border at top and bottom, justifyContent: stretch, padding: 0.5rem */ <Text cls="white tc"> /* white color, text-align: center */ Something </Text> </View> [0] http://tachyons.io/docs/layout/spacing/ http://tachyons.io/docs/layout/spacing/ [1] http://tachyons.io/docs/typography/scale/ http://tachyons.io/docs/typography/scale/
- mxstbr 10y agoThat's awesome, I love tachyons! styled-components is on a slightly "lower" level in a certain sense, you would build components like yours with styled-components: const TachyonsText = styled.Text` ${props => props.bt ? 'some: styles;' : 'other: styles;'} `; Those functions could then be extracted and reused across your components: const bt = (props) => props.bt ? 'some: styles;' : 'other: styles;'; const TachyonsText = styled.Text` ${bt} ${bb} ${jcfs} `; And then you can use your component like any other tachyons component: <TachyonsText bt bb>Text here</TachyonsText>
- mxstbr 10y agoTo elaborate on this just a tiny bit, you can use tachyons-js[0] by the amazing jongold to automate even more of this: import tachyons from 'tachyons-js'; const tachyonsHelperFunc(props) => Object.keys(props).map(prop => tachyons[prop]) const MyTachyonsComp = styled.div`${tachyonsHelperFunc}`; This way, MyTachyonsComp can now has all the benefits of styled-components (easy theming and overriding, power of JS for styling, ReactNative, nesting,…) while also being able to use tachyons really easily: <MyTachyonsComp ma2 ph2 bb /> In fact, you could probably even wrap the above helper to make it really easy to use: const styledTachyonsComponent = (...args) = styled(..args)`${tachyonsHelperFunction}`; Now you can created styled-tachyons-components really easily: const MyTachyonsStyledDiv = styledTachyonsComponent('div'); :tada: Note: I just coded this in this comment, might be some typos in there. [0]: https://github.com/jongold/tachyons-js https://github.com/jongold/tachyons-js
- anilgulecha 10y agoWhat's the font in the code-editor screenshot? The italics look good!
- mxstbr 10y agoIt's Operator Mono by Hoefler & Co! http://www.typography.com/fonts/operator/overview/ http://www.typography.com/fonts/operator/overview/
- deleted 10y ago[deleted]
- elecengin 10y agoHow do you do pseudo classes like :focus?
- mxstbr 10y agoLike this: const FocusInput = styled.input` &:focus { focus-styles: here; } `;
- jeswin 10y agoglamor is another option for React apps, if inline styling is your thing. https://github.com/threepointone/glamor https://github.com/threepointone/glamor
- mxstbr 10y agoglamor is amazing, Sunil really outdid himself with it. In fact, his injection mechanism is so good we blatantly copied it for styled-components! On the other side, Sunil is looking into stealing some of the general ideas from styled-components which I'm really looking forward to: https://github.com/threepointone/glamor/issues/70 https://github.com/threepointone/glamor/issues/70
- retox 10y agoSite is a blank page for me.
- mxstbr 10y agoWhich browser/OS? (Feel free to dig into the code and submit a PR if you're so inclined! https://github.com/styled-components/styled-components.github.io https://github.com/styled-components/styled-components.githu...)
- retox 10y agoApologies, didn't see your reply until now. IE11 behind the company firewall, I can see a rather short set of complete HTML in the source but nothing is rendered. Sorry I can't offer more information.
- cfv 10y agoNeat. Now, why not actual CSS?
- mxstbr 10y agoCan I forward you to these four resources? (I realize this might sound like a cop-out answer, but these people have summed up the benefits of CSS-in-JS so much better than I could in two minutes!) [0]: Rendering Khan Academy’s Learn Menu Wherever I Please: Documenting the move from the handlebars + less combo to react and css-in-js, and why KhanAcademy did it [1]: My thoughts on Inline Styles: A great collection of both pros and cons about styles in javascript. Most of those doubts we've tried to solve with styled-components [2]: "Scale" FUD and Style Components: Using components as low-level styling constructs [3]: Ryan's random thoughts about inline styles: Explaining some benefits of using styles in js BONUS [4] The Future of Reusable CSS: How component libraries should be styled, and why they're not yet ---- [0]: https://medium.com/@jdan/rendering-khan-academys-learn-menu-wherever-i-please-4b58d4a9432d#.w9nshye05 https://medium.com/@jdan/rendering-khan-academys-learn-menu-... [1]: https://medium.com/@andrewingram/my-thoughts-on-inline-styles-da94682b5e35#.trbnpmcn9 https://medium.com/@andrewingram/my-thoughts-on-inline-style... [2]: https://medium.com/learnreact/scale-fud-and-style-components-c0ce87ec9772#.kzjba8lcg https://medium.com/learnreact/scale-fud-and-style-components... [3]: https://www.youtube.com/watch?v=EkPcGS4TzdQ https://www.youtube.com/watch?v=EkPcGS4TzdQ [4]: https://www.youtube.com/watch?v=XR6eM_5pAb0 https://www.youtube.com/watch?v=XR6eM_5pAb0
- cfvergara 10y agoNeat. Thanks!
- rojobuffalo 10y agoAm I an outlier for enjoying plain CSS? I get everything I need and want with css-modules, classnames/bind, and the occasional inline style.
- drinchev 10y agoWhat is the performance penalty of using generated styles on every render? As far as I can see from the source code, React will have to modify `<style>` tag every time a component is being rendered. I still think the best way to handle stylesheets is with external css file ( doesn't matter how it's generated. I use CSSModules ) and then add static class names for those components.
- mxstbr 10y agoWe've tried styled-components in medium-size projects (50-500 components) and haven't noticed any performance-hit yet. That being said, it's definitely something we're conscious about. That's why we will be writing a babel transform that grabs all the _static_ styles and extracts them into a separate stylesheet! (just didn't have time to do it until ReactNL where I just announced it) See this issue for more information, and if anybody reading this has experience with babel transforms please holla since we can definitely use your help! https://github.com/styled-components/styled-components/issues/59 https://github.com/styled-components/styled-components/issue...
- onetom 10y agoYou mean extract into a separate stylesheet file? Wouldn't that lead to https://en.wikipedia.org/wiki/Flash_of_unstyled_content https://en.wikipedia.org/wiki/Flash_of_unstyled_content issues? Maybe some memoization could help if there are performance issues with regenerating `document.styleSheets`...
- bastawhiz 10y agoWithin React there are two approaches: 1. It uses the `style` prop, which modifies the CSSStyleDeclaration object on the DOM node. The style attribute gets set by the browser behind the scenes. [1] 2. The rendering happens on the server, and React produces the markup for the style attribute. [2] The former approach has very little overhead. The second bears the overhead of having to be parsed. In most libraries, this is what gets used. Some libraries try to be clever, though, and inject `<style>` or `<link>` elements into the DOM (mostly to support things like `:hover`). This can get extremely CPU intensive, though, and it's not uncommon to get burned by a library in this way. [1] https://github.com/facebook/react/blob/c78464f8ea9a5b00ec80252d20a71a1482210e57/src/renderers/dom/shared/CSSPropertyOperations.js#L194 https://github.com/facebook/react/blob/c78464f8ea9a5b00ec802... [2] https://github.com/facebook/react/blob/c78464f8ea9a5b00ec80252d20a71a1482210e57/src/renderers/dom/shared/CSSPropertyOperations.js#L167 https://github.com/facebook/react/blob/c78464f8ea9a5b00ec802...
- andrewvijay 10y agoGreat one! Would love to do this in my side projects.
- mxstbr 10y agoLet us know how it goes, we'd love to know what you think! Note: You can also use this in real projects ;)
- andrewvijay 10y agoReal projects in the future may be! Because the current one involves a lot of components and I don't think this would be scaling well as it's gonna rerender the styles multiple times.
- mxstbr 10y agoSorry, how do you mean "rerender the styles multiple times"? The only time any styles ever change is if one of your interpolations changes, but otherwise we don't do much calculation at all! That being said, there might be a performance impact in massive (1000+ components) applications. We've tried it in medium apps, and haven't seen any performance impact yet. We're also going to build a babel transform to extract the static styles to get even better performance. (see https://news.ycombinator.com/item?id=12700280 https://news.ycombinator.com/item?id=12700280)
- andrewvijay 10y agoHmm yup I mistyped that. I was a bit worried about the performance because the app is a multi tab grafana like dashboard with real time data. I'll try by modifying components that dont change often. Will measure and go up from there.
- z3t4 10y agoWith components I think we are taking a step back from semantic HTML elements, where style is applied by a separate template. And business logic is also separated from the layout elements.
- danneu 10y agoThe cutting edge of front-end development has been arriving at ways to split business logic from layout elements for some time now. Redux, Om, Reframe, Elm, etc. They all amount to hooking up components to a state transactor where the business logic lives separately. Semantic HTML seems like a trade-off where you clean your markup at the expense of indirection, not a universal aspiration. And components don't dictate where your styling should live.
- z3t4 10y agoIn classic HTML you use id attributes for the JavaScript, and class attributes for the style-sheet.
- King-Aaron 10y agoI agree, I still don't see the benefit here.
- deleted 10y ago[deleted]
- himlion 10y agoSaw your talk this morning at reactnl, cool stuff!
- mxstbr 10y agoHah, small world! (if you want to call HN small) Glad you liked it :)
- nmalaguti 10y agoFor anyone unfamiliar with the syntax used to achieve this, it's called Tagged Template Literals [0] and it's part of ES2015. You have a function that receives the static strings and interpolations and can return anything you want. [0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- AgentME 10y agoOne of my favorite uses of tagged template literals is for HTML-encoding variables into an HTML string with (my module) https://www.npmjs.com/package/auto-html https://www.npmjs.com/package/auto-html.
- andreypopp 10y agoI think using strings as an API is a step in the wrong direction. I like that it produces a React component directly though. We experimented with styling approaches for React a while ago and produced our solution — React Stylesheet[1], which we used for over an year in different React applications. It also produces components out of style definitions directly: let GreenBox = style('div', { base: { background: 'green' } }) Which you can use like any other React component later: <GreenBox /> As you can see the API is kinda similar but uses JS instead of CSS string. What are advantages? The following: * Consistent syntax: you can use functions, variabls, mixins, w/o the need for interpolation `${...}`. * Tooling. This is big one. You can make your stylesheets linted with ESLint and typesafe (!!!) with FlowType or TypeScript. FlowType is supported out of the box, see [2]. Typesafe stylesheets is a huge win for productivity, I constantly catch typos and invalid values via Flow. [1]: https://github.com/prometheusresearch/react-stylesheet/blob/next/README.md https://github.com/prometheusresearch/react-stylesheet/blob/... [2]: https://github.com/prometheusresearch/react-stylesheet/blob/next/README.md#type-safety https://github.com/prometheusresearch/react-stylesheet/blob/... EDIT: additions Styles are compiled into CSS so :hover and friends work here.
- mxstbr 10y agoHey Andrey! :wave: If you reading this are interested in a discussion about this, read this tweet by Andrey and the following replies: https://twitter.com/andreypopp/status/786524437843615744 https://twitter.com/andreypopp/status/786524437843615744 :)
- deleted 10y ago[deleted]
- Raphmedia 10y agoEmoji as CSS classes. Never thought of that one...
- gjolund 10y agoVery cool, I have been playing around with this idea for a little bit now and your implementation looks solid. Looking forward to giving this a shot on my next side project.
- pgt 10y agoAfter Reagent + Hiccup, I'm ruined. Nothing feels as natural as a full, general-purpose language (Clojure) combined with a natural keyword-based DSL for styling: (defn right-cell [& body] [:td.right.aligned body]) ;; renders <td class="right aligned>{...body}</td> (defn person-row [{:keys [name age] :as p}] [:tr [:td name] [right-cell age]]) (defn person-table [font-size people] (let [heading-size (* font-size 1.6)] [:div [:h1 {:style {:font-size (str heading-size "em")} "People List"] [:table.ui.basic.table [:tbody (map person-row people)]]])) (defn main [] [person-table 2 [{:name "John" :age 21} {:name "Sally" :age 22}])