# Linaria > Linaria exposes a core`css`method alongside with small, but just enough amount of helpers. Inside`@linaria/core`module you can find following methods: --- # Linaria Documentation # Source: https://raw.githubusercontent.com/callstack/linaria/master/docs/API.md # Path: docs/API.md # API Linaria exposes a core `css` method alongside with small, but just enough amount of helpers. Inside `@linaria/core` module you can find following methods: ## Client APIs ### `css` String tag for tagged template literals consisting CSS code. The tagged template literal is evaluated to a unique class name by the Babel plugin: ```js import { css } from '@linaria/core'; const flower = css` display: inline; color: violet; `; // flower === flower__9o5awv –> with babel plugin ``` All rules inside the template literal are scoped to the class name, including media queries and animations. For example, we can declare CSS animation like so: ```js import { css } from '@linaria/core'; const box = css` animation: rotate 1s linear infinite; @keyframes rotate { { from: 0deg; } { to: 360deg; } } `; ``` ### `cx(...classNames: Array) => string` Takes a list of class names and returns a concatenated string with the class names. Falsy values are ignored. ```js import { css, cx } from '@linaria/core'; const cat = css` font-weight: bold; `; const yarn = css` color: violet; `; const fun = css` display: flex; `; function App({ isPlaying }) { return ; } ``` Unlike the [`classnames`](https://www.npmjs.com/package/classnames) library, this doesn't handle objects. If you want or need the features of the `classnames` library, you can use it instead. ### `styled` Helper to build React components. It allows you to write your components in a similar syntax as [`styled-components`](https://www.styled-components.com/): The syntax is similar to the `css` tag. Additionally, you can use function interpolations that receive the component's props: ```js import { styled } from '@linaria/react'; import colors from './colors.json'; const Container = styled.div` background-color: ${colors.background}; color: ${(props) => props.color}; width: ${100 / 3}%; border: 1px solid red; &:hover { border-color: blue; } `; ``` All rules inside the template literal are scoped to the component, similar to the `css` tag. Dynamic function interpolations are replaced with CSS custom properties. A dynamic function interpolation will receive the `props` of the component as it's arguments and the returned result will be used as the value for the variable. When using this, a tiny helper is imported so that we don't duplicate the code for creating the component in all files. You can also interpolate a component to refer to it: ```js const Title = styled.h1` font-size: 36px; `; const Article = styled.article` font-size: 16px; /* this will evaluate to the selector that refers to `Title` */ ${Title} { margin-bottom: 24px; } `; ``` If you want to swap out the tag that's rendered, you can use the `as` prop: ```js // Here `Button` is defined as a `button` tag const Button = styled.button` background-color: rebeccapurple; `; // You can switch it to use an `a` tag with the `as` prop ; ``` You can also decorate another styled component with `styled`: ```js const Button = styled.button` background-color: rebeccapurple; `; // The background-color in FancyButton will take precedence const FancyButton = styled(Button)` background-color: black; `; ``` ### Atomic `css` In addition to `css` from `@linaria/core`, the `@linaria/atomic` package exports its own `css` template literal which produces _atomic_ styles. See [the atomic css documentation](./ATOMIC_CSS.md) on this for more information. ## Server APIs (`@linaria/server`) ### `collect(html: string, css: string) => string` Takes HTML and CSS strings and returns the critical CSS used in the page by analyzing the class names. It can be used to determine critical CSS for server side rendering. ```js import { collect } from '@linaria/server'; const css = fs.readFileSync('./dist/styles.css', 'utf8'); const html = ReactDOMServer.renderToString(); const { critical, other } = collect(html, css); // critical – returns critical CSS for given html // other – returns the rest of styles ``` This will only detect critical CSS based on class names, so if you have any other type of selectors, they'll get added to the critical CSS. Also note that extracting critical CSS this way will change the order of class names. It's not a problem if you're primarily using Linaria for styling. However if you're using a third party framework which imports its own CSS, then it's not recommended to use this helper on the extracted CSS. --- # Linaria Documentation # Source: https://raw.githubusercontent.com/callstack/linaria/master/docs/ATOMIC_CSS.md # Path: docs/ATOMIC_CSS.md # Atomic CSS ## What is Atomic CSS? Atomic CSS is an approach to styling that reduces payload sizes for style delivery, and allows style composition and reuse easily. This document describes the concept of Atomic CSS, its advantage and use cases. Atomic CSS is a way of writing CSS such that each CSS rule has exactly one declaration (an "atom"). For example, ```css /** A normal class */ .myClass { background: red; width: 100%; height: 100%; } /** Can be written atomically as: */ .a { background: red; } .b { width: 100%; } .c { height: 100%; } ``` ## Usage in Linaria Atomic styles can be enabled in the linaria config by providing an `atomizer` function (see [configuration](./CONFIGURATION.md) for details). Once enabled, it is possible to write atomic styles by importing the `css` template literal from `@linaria/atomic`: ```tsx import { cx } from '@linaria/core'; import { css } from '@linaria/atomic'; const atomicCss = css` background: red; width: 100%; height: 100%; border: 1px solid black; `; const blueBackground = css` background: blue; border: 1px solid black; `; // In React:
; // In vanilla JS: const div = document.createElement('div'); div.setAttribute('class', cx(atomicCss, blueBackground)); document.body.appendChild(div); ``` Which at build time, is transformed into: ```ts import { cx } from '@linaria/core'; import { css } from '@linaria/atomic'; const atomicCss = 'atm_background_abcd atm_width_efgh atm_height_ijkl atm_border_mnop'; const blueBackground = 'atm_background_qrst atm_border_mnop'; // In React:
; //
// In vanilla JS: const div = document.createElement('div'); div.setAttribute('class', cx(atomicCss, blueBackground)); // same as React example document.body.appendChild(div); ``` (Note: in the example above, the slugs in the atoms are lengthened for readability) The format of these atoms is `atm_${propertySlug}_${valueSlug}` which lets us deduplicate based on the `propertySlug` part of the atom. As you can see in the above example, `atm_border_mnop` can be removed as it duplicated, and we see two atoms with the `background` property slug, and can remove one of them. ### at-rules, pseudo classes and keyframes Linaria's atomic css also supports creating (nested) at-rules, pseudo classes and keyframes: ```ts import { css } from '@linaria/atomic'; // Note: animation name namespacing does not happen automatically with @linaria/atomic. Keyframe animations are pulled out to the top level and not atomized. export const animation = css` @keyframes my-animation { from { opacity: 0; } to { opacity: 1; } } animation: my-animation 1s infinite; `; export const pseudoClass = css` &:hover { color: pink; } `; export const mediaQuery = css` @media (max-width: 400px) { background: orange; } `; ``` These can also be combined for further nesting. ### Property priorities Using atomic CSS, longhand properties such as `padding-top` have a _higher_ priority than their shorthand equivalents like `padding`. For example: ```ts import { css } from '@linaria/atomic'; const noPadding = css` padding: 0; `; const paddingTop = css` padding-top: 5px: `; // In react:
...
; ``` The result will be that the div has `padding-top: 5px;`, as that is higher priority than `padding: 0`. The way linaria achieves this is through property priorities. See [this blog post](https://weser.io/blog/the-shorthand-longhand-problem-in-atomic-css) for more details on the concept, and the problems it solves. The method used in linaria is to increase the specificity of the rules: see `@linaria/atomic`'s `propertyPriority` function for a list of longhand and shorthand properties supported by this. The basic rules are: - Longhand properties have higher priority than shorthand properties - Declarations in @media rules (and any @-rule, such as @supports) have higher priority than those outside of them ## Use cases ### Reducing number of rules One advantage of writing styles in this way is that we can reuse CSS more effectively. In many cases, declarations are repeated in CSS, and atomic CSS allows heavy reuse of these classes. For example if we have the classes, ```html //here I use it ); export default Header; ``` > You can also use the `styled` variant, importing from `@linaria/react`. If you run `npm run dev`, you should be able to see a button next to the nav title, with red bold text. You can take a look at this example [here](../examples/Preact) ## Gatsby If you wish you use Gatsby, we recommend you to use the `gatsby-cli` and start from there. The following configuration assumes you are using the default template provided by gatsby-cli. Start by creating your project using: ``` npx gatsby new my-project ``` Now, you have two options. You can use `gatsby-plugin-linaria` or create a custom config. ### gatsby-plugin-linaria This is an easier and more straightforward way of integrating Linaria with Gatsby. Check [plugin docs](https://github.com/cometkim/gatsby-plugin-linaria) for instructions. You can also take a look at the example [here](../examples/gatsby/plugin) ### Custom config This is a bit more advanced way of integrating Linaria into your Gatsby project. First, you will need to install `@linaria/babel-preset` and `babel-preset-gatsby`. Then, create `babel.config.js` in the root of your project with the following contents: ```js module.exports = { presets: [ 'babel-preset-gatsby', [ '@linaria', { evaluate: true, displayName: process.env.NODE_ENV !== 'production', }, ], ], }; ``` You can read more about configuring Babel in Gatsby projects in [their docs](https://www.gatsbyjs.org/docs/babel/). Besides that, you will need to alter Gatsby's Webpack config to modify the Babel loader. This can be done in `gatsby-node.js` file. Consider the following snippet: ```js exports.onCreateWebpackConfig = ({ actions, loaders, getConfig, stage }) => { const config = getConfig(); config.module.rules = [ ...config.module.rules.filter( (rule) => String(rule.test) !== String(/\.js?$/) ), { ...loaders.js(), test: /\.js?$/, loader: '@linaria/webpack-loader', options: { sourceMap: stage.includes('develop'), displayName: stage.includes('develop'), babelOptions: { presets: ['babel-preset-gatsby'], }, }, exclude: /node_modules/, }, ]; actions.replaceWebpackConfig(config); }; ``` If you want to know more about extending Webpack config in Gatsby projects, check out [relevant Gatsby docs](https://www.gatsbyjs.org/docs/add-custom-webpack-config/). With that done, you should be all set! You can take a look at the minimal example using the above configuration [here](../examples/gatsby/custom-config). --- # Linaria Documentation # Source: https://raw.githubusercontent.com/callstack/linaria/master/docs/CRITICAL_CSS.md # Path: docs/CRITICAL_CSS.md # Critical CSS extraction Since Linaria extracts the CSS statically at build time, you don't need to setup a server rendering. Usually, critical CSS extraction will be automatic if you are code splitting your code and using something like [mini-css-extract-plugin](https://github.com/webpack-contrib/mini-css-extract-plugin) for webpack to generate your CSS files. If you're not code splitting, or the initial CSS chunk is not representative of initially rendered content, you might want to extract critical CSS using the `collect` helper we provide to ship the minimal amount of CSS used in the page to the browser. To be able to use the `collect` helper, you need to provide the initial HTML, which usually means that you need to have SSR setup for your web app. The `collect` method takes some HTML and CSS and gives you the critical CSS: ```js import { collect } from '@linaria/server'; const { critical, other } = collect(html, css); ``` For example, in an express app with React, you could do something like the following: ```js import fs from 'fs'; import express from 'express'; import crypto from 'crypto'; import React from 'react'; import ReactDOMServer from 'react-dom/server'; import { collect } from '@linaria/server'; import App from './App'; const cache = {}; const css = fs.readFileSync('./dist/styles.css', 'utf8'); const app = express(); app.get('/', (req, res) => { const html = ReactDOMServer.renderToString(); const { critical, other } = collect(html, css); const slug = crypto.createHash('md5').update(other).digest('hex'); cache[slug] = other; res.end(` App
${html}
`); }); app.get('/styles/:slug', (req, res) => { res.type('text/css'); res.end(cache[req.params.slug]) }); app.listen(3242); ``` By placing the non-critical CSS at the end of `body`, you can make sure that page rendering is not blocked until the CSS is loaded. You can also load the non-critical CSS lazily with JavaScript once the page has loaded for a more efficient strategy. However, it's highly recommended that you take advantage of code splitting in webpack which gives you automatic CSS chunks in addition to critical CSS. --- # Linaria Documentation # Source: https://raw.githubusercontent.com/callstack/linaria/master/docs/DYNAMIC_STYLES.md # Path: docs/DYNAMIC_STYLES.md # Dynamic styles with `css` tag Sometimes we have some styles based on component's props or state, or dynamic in some way. If you use the `styled` helper with React, this is automatically handled using CSS custom properties. But we cannot do the same for `css` tags since they aren't linked to any component, and so we don't have access to state and props. However, there are some approaches to tackle this, each with their own limitations. ## Inline styles Inline styles are the most straightforward way to use dynamic styles. Pass a `style` object with the dynamic styles, and you're done. ```js import React from 'react'; export function Pager({ index, children }) { return (
{children}
); } ``` However, it's not possible to use inline styles with pseudo-selectors or media queries. ## CSS custom properties [CSS custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/--*) can be used to expose dynamic properties to the CSS. ```js import React from 'react'; import { css } from '@linaria/core'; const box = css` height: var(--box-size); width: var(--box-size); `; export function Box({ size }) { return (
); } ``` The [browser support for CSS custom properties](http://caniuse.com/#feat=css-variables) is limited, and it's not polyfilled. Therefore it's not a viable approach if you need to support older browsers. Worth noting that custom properties cascade, so if you don't override the value for the current element, and a custom property with the same name exists for a parent element, it'll be used instead. ## Data attributes In cases where you know the values ahead of time, you can use [data attributes](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes) to dynamically switch the styles that are applied. ```js import React from 'react'; import { css } from '@linaria/core'; const box = css` &[data-valid] { color: yellow; } &[data-valid="invalid"] { color: red; } &[data-valid="valid"] { color: green; } ` export function Box({ color, valid }) { return (
); } ``` ## `currentColor` For color values, browsers support a `currentColor` property which points to the text color of the element. It is well supported in all browsers. ```js import React from 'react'; import { css } from '@linaria/core'; const box = css` background-color: currentColor; `; const content = css` color: white; `; export function Box({ color }) { return (
¯\_(ツ)_/¯
); } ``` You cannot use this approach if the dynamic value is not a color, or the element contains some text which needs to be styled with a different color. If the element has children, you will need to reset the `color` property for the text. --- # Linaria Documentation # Source: https://raw.githubusercontent.com/callstack/linaria/master/docs/FEATURE_FLAGS.md # Path: docs/FEATURE_FLAGS.md # Feature Flags Feature flags are used to enable or disable specific features provided. The `features` option in the configuration allows you to control the availability of these features. ## Syntax for Specifying Flags - `true`: Enables the feature for all files. - `false`: Disables the feature for all files. - `"glob"`: Enables the feature only for files that match the specified glob pattern. - `["glob1", "glob2"]`: Enables the feature for files matching any of the specified glob patterns. - `["glob1", "!glob2"]`: Enables the feature for files matching `glob1` but excludes files that match `glob2`. # `dangerousCodeRemover` Feature The `dangerousCodeRemover` is a flag that is enabled by default. It is designed to enhance the static evaluation of values that are interpolated in styles and to optimize the processing of styled-wrapped components during the build stage. This optimization is crucial for maintaining a stable and fast build process. It is important to note that the `dangerousCodeRemover` does not impact the runtime code; it solely focuses on the code used during the build. ## How It Works During the build process, Linaria statically analyzes the CSS-in-JS codebase and evaluates the styles and values that are being interpolated. The `dangerousCodeRemover` steps in at this stage to remove potentially unsafe code, which includes code that might interact with browser-specific APIs, make HTTP requests, or perform other runtime-specific operations. By removing such code, the evaluation becomes more reliable, predictable, and efficient. ## Benefits Enabling the `dangerousCodeRemover` feature provides several benefits: 1. **Stability**: The removal of potentially unsafe code ensures that the build process remains stable. It minimizes the chances of encountering build-time errors caused by unsupported browser APIs or non-static operations. 2. **Performance**: Removing unnecessary code results in faster build times. The build tool can efficiently process and evaluate the styles and components without unnecessary overhead, leading to quicker development cycles. ## Fine-Tuning the Removal While the `dangerousCodeRemover` is highly effective at optimizing the build process, there may be cases where it becomes overly aggressive and removes code that is actually required for your specific use case. In such situations, you have the flexibility to fine-tune the behavior of the remover. By leveraging the `features` option in the configuration, you can selectively disable the `dangerousCodeRemover` for specific files. This allows you to preserve valuable code that may not be safely evaluated during the build process. ### Example Suppose you have a file named `specialComponent.js` that contains code that should not be deleted. By adding the following entry to your `features` configuration: ```js { features: { dangerousCodeRemover: ["**/*", "!**/specialComponent.js"], }, } ``` You are instructing Linaria to exclude the `specialComponent.js` file from the removal process. As a result, any code within this file that would have been removed by the `dangerousCodeRemover` will be retained in the build output. # `globalCache` Feature The `globalCache` is enabled by default. Linaria uses two levels of caching to improve the performance of the build process. The first level is used to cache transformation and evaluation results for each `transform` call, usually a single call of Webpack's loader or Vite's transform hook. The second level is used to cache the results of the entire build process. The `globalCache` feature controls the second level of caching. Turning off this feature will result in a slower build process but decreased memory usage. # `happyDOM` Feature The `happyDOM` is enabled by default. This feature enables usage of https://github.com/capricorn86/happy-dom to emulate a browser environment during the build process. Typically, the `dangerousCodeRemover` feature should remove all browser-related code. However, some libraries may still contain browser-specific code that cannot be statically evaluated. In such cases, the `happyDOM` feature can be used to emulate a browser environment during the build process. This allows Linaria to evaluate the code without encountering errors caused by missing browser APIs. # `softErrors` Feature The `softErrors` is disabled by default. It is designed to provide a more lenient evaluation of styles and values that are interpolated in styles. This flag is useful for debugging and prevents the build from failing even if some files cannot be processed with Linaria. # 'useBabelConfigs' Feature The `useBabelConfigs` feature is enabled by default. If it is enabled, Linaria will try to resolve the `.babelrc` file for each processed file. Otherwise, it will use the default Babel configuration from `babelOptions` in the configuration. Please note that the default value of `useBabelConfigs` will be changed to `false` in the next major release. --- # Linaria Documentation # Source: https://raw.githubusercontent.com/callstack/linaria/master/docs/HOW_IT_WORKS.md # Path: docs/HOW_IT_WORKS.md # How it works Linaria consists of 2 parts: 1. Babel plugin 2. Bundler integration ## Babel plugin The Babel plugin will look for `css` and `styled` tags in your code, extract the CSS out and return it in the file's metadata. It will also generate unique class names based on the hash of the filename. > To get a deep dive into Linaria babel plugin internals, check [debugging section of Contributing docs](../CONTRIBUTING.md#debugging-and-deep-dive-into-babel-plugin) When using the `styled` tag, dynamic interpolations will be replaced with CSS custom properties. References to constants in the scope will also be inlined. If the same expression is used multiple times, the plugin will create a single CSS custom property for those. The interpolations used for the CSS custom properties are left in the file, and are passed to the helper which creates the React components. Function interpolations receive the component's props and their return value will be used as the value for the CSS custom property. For other expressions, their result is used as is. If the resulting values aren't strings, they'll be converted to a string before setting the property. Inline styles are used to set the custom properties. For example, the plugin will transpile this: ```js import { styled } from '@linaria/react'; import { families, sizes } from './fonts'; const background = 'yellow'; const Title = styled.h1` font-family: ${families.serif}; `; const Container = styled.div` font-size: ${sizes.medium}px; background-color: ${background}; color: ${props => props.color}; width: ${100 / 3}%; border: 1px solid red; &:hover { border-color: blue; } `; ``` To this: ```js import { styled } from '@linaria/react'; import { families, sizes } from './fonts'; const background = 'yellow'; const Title = styled('h1')({ name: 'Title', class: 'Title_t1ugh8t', vars: { 't1ugh8t9-0': [families.serif], }, }); const Container = styled('div')({ name: 'Container', class: 'Container_c1ugh8t', vars: { 'c1ugh8t9-0': [sizes.medium, 'px'], 'c1ugh8t9-2': [props => props.color], }, }); ``` The extracted CSS will look something like this: ```css .Title_t1ugh8t9 { font-family: var(--t1ugh8t-0); } .Container_c1ugh8t9 { font-size: var(--c1ugh8t-0); background-color: yellow; color: var(--c1ugh8t-2); width: 33.333333333333336%; border: 1px solid red; } .Container_c1ugh8t9:hover { border-color: blue; } ``` If we encounter a valid unit directly after the interpolation, it'll be passed to the helper so that the correct unit is used when setting the property. This allows you to write this: ```js const Title = styled.h1` font-size: ${large}px; `; ``` Instead of having to write this: ```js const Title = styled.h1` font-size: ${large + 'px'}; `; ``` It's necessary since if we just replaced the interpolation as is, it wouldn't be a valid syntax: ```css .Title_t1ugh8t9 { font-size: var(--t1ugh8t9-0-0)px; /* you can't have 'px' after the `var(..)` */ } ``` If we encounter a JS object when inlining, the JS object is assumed to be a style rule and converted to a CSS string before inlining it. For example, if you write this: ```js const absoluteFill = { position: 'absolute', top: 0, right: 0, bottom: 0, left: 0, }; const Container = styled.h1` background-color: papayawhip; ${Box} { ${absoluteFill} } `; ``` It is equivalent to writing this: ```js const Container = styled.h1` background-color: papayawhip; ${Box} { position: absolute; top: 0; right: 0; bottom: 0; left: 0; } `; ``` We support this usage because it allows you to use a library such as [polished.js](https://polished.js.org) which outputs object based styles along with Linaria. If you've configured the plugin to evaluate expressions with `evaluate: true` (default), any dynamic expressions we encounter will be evaluated during the build-time in a sandbox, and the result will be included in the CSS. Since these expressions are evaluated at build time in Node, you cannot use any browser specific APIs or any API which is only available in runtime. Access to Node native modules such as `fs` is also not allowed inside the sandbox to prevent malicious scripts. In addition, to achieve consistent build output, you should also avoid doing any side effects in these expressions and keep them pure. You might want to skip evaluating a certain interpolation if you're using a browser API, a global variable which is only available at runtime, or a module which breaks when evaluating in the sandbox for some reason. To skip evaluating an interpolation, you can always wrap it in a function, like so: ```js const Box = styled.h1` height: ${() => window.innerHeight * 2}; `; ``` But keep in mind that if you're doing SSR for your app, this won't work with SSR. In this particular case, better option will be to use the `calc` function along with the `vh` unit for the viewport height (e.g. `calc(100vh * 2)`). ### Evaluators Linaria can use different strategies for evaluating the interpolated values. Currently, we have two built-in strategies: - `extractor` was the default strategy in `1.x` version. It takes an interpolated expression, finds all the referenced identifiers, gets all its declarations, repeats cycle for all identifiers in found declarations, and then constructs a new tree of statements from all found declarations. It's a pretty simple strategy, but it significantly changes an evaluated code and doesn't work for non-primitive js-constructions. - `shaker` was introduced as an option in `1.4` and became the default in `2.0` version. In contrast to `extractor`, `shaker` tries to find all irrelevant code and cuts it out of the file. As a result, interpolated values can be defined without any restrictions. If an interpolated value or one of its dependencies is imported from another module, that module will be also processed with an evaluator (the implementation of evaluator will be chosen by matching `rules` from [the Linaria config](./CONFIGURATION.md#options)). Sometimes it can be useful to implement your own strategy (it can be just a mocked version of some heavy or browser-only library). You can do it by implementing `Evaluator` function: ```typescript type Evaluator = ( filename: string, // the name of processed file options: StrictOptions, // Linaria config text: string, // source code only: string[] | null // list of exported values or `null` for everything ) => [string, Map | null]; ``` The function should return an array with two elements: source code prepared for evaluation and `Map` with imported files in keys and list of the identifiers in values. ## Bundler integration Plugins for bundlers such as webpack and Rollup use the Babel plugin internally and write the CSS text along with the sourcemap to a CSS file. The CSS file is then picked up and processed by the bundler (e.g. - `css-loader` in case of webpack) to generate the final CSS. --- # Linaria Documentation # Source: https://raw.githubusercontent.com/callstack/linaria/master/docs/LINTING.md # Path: docs/LINTING.md # Linting There are separate installations based on whether you use stylelint v13 or stylelint v14 ## Stylelint 13 For linting styles with [stylelint 13](https://stylelint.io/), use `@linaria/stylelint`. ### Installation Install `stylelint` and optionally your favorite config (such as `stylelint-config-recommended`) in your project: ```bash yarn add --dev stylelint stylelint-config-recommended @linaria/stylelint ``` ### Configuring stylelint All you need to do is to set your config to extend from `@linaria/stylelint`. Here's the example `.stylelintrc` configuration file: ```json { "extends": [ "stylelint-config-recommended", "@linaria/stylelint" ] } ``` Please refer to the [official stylelint documentation](https://stylelint.io/user-guide/configuration/) for more info about configuration. The preprocessor will use the [options from the configuration file](/docs/CONFIGURATION.md) for processing your files. ## Stylelint 14 For linting styles with [stylelint 14](https://stylelint.io/), use `@linaria/stylelint-config-standard-linaria`. ### Installation Install `stylelint` and `@linaria/stylelint-config-standard-linaria` ```bash yarn add --dev stylelint @linaria/stylelint-config-standard-linaria ``` ### Configuring stylelint For the standard configuration you can extend from `@linaria/stylelint-config-standard-linaria`. Here's an example `.stylelintrc` configuration file: ```json { "extends": [ "@linaria/stylelint-config-standard-linaria" ] } ``` `@linaria/stylelint-config-standard-linaria` extends `stylelint-config-standard` which extends `stylelint-config-recommended` so you do NOT need to add those separately. It also sets the customSyntax as `@linaria/postcss-linaria` and adds a few rules. Alternatively, to just use the custom syntax you can add `@linaria/postcss-linaria` Here's an example `.stylelintrc` configuration file: ```json { "customSyntax": "@linaria/postcss-linaria" } ``` Please refer to the [official stylelint documentation](https://stylelint.io/user-guide/configuration/) for more info about configuration. ### Why did the configuration change between Stylelint v13 and v14? Stylelint 14 encourages the use of a [custom syntax](https://stylelint.io/developer-guide/syntaxes/) instead of a processor. `@linaria/stylelint-config-standard-linaria` sets the custom syntax to `@linaria/postcss-linaria`, a custom syntax for linaria, whereas @linaria/stylelint uses a processor. The custom syntax has the benefit of being able to support `stylelint --fix` whereas the processor cannot. ## Usage ### Linting your files Add the following to your `package.json` scripts: ```json "lint:css": "stylelint src/**/*.js" ``` Now, you can run `yarn lint:css` to lint the CSS in your JS files with stylelint. For more information refer to [stylelint documentation](https://stylelint.io/user-guide/cli/). ## Editor Setup In order to make the [vscode-stylelint](https://github.com/stylelint/vscode-stylelint) extension work with this syntax correctly, you must configure it to validate the files you use linaria in by specifying an array of [language identifiers](https://code.visualstudio.com/docs/languages/overview#_changing-the-language-for-the-selected-file). You can do this by following these [instructions](https://github.com/stylelint/vscode-stylelint#stylelintvalidate). For example: ```json { "stylelint.validate": ["typescriptreact"] } ``` --- # Linaria Documentation # Source: https://raw.githubusercontent.com/callstack/linaria/master/docs/MIGRATION_GUIDE.md # Path: docs/MIGRATION_GUIDE.md # Migration Guide # 6.x from 5.x, 4.x, 3.x ## For Users The main breaking change is that all tooling has been moved from the `@linaria` scope to the `@wyw-in-js` scope. This means that you will need to update your dependencies as follows: | Old | New | --- | --- |@linaria/babel-preset | @wyw-in-js/babel-preset |@linaria/cli | @wyw-in-js/cli |@linaria/esbuild | @wyw-in-js/esbuild |@linaria/rollup | @wyw-in-js/rollup |@linaria/shaker | discontinued |@linaria/vite | @wyw-in-js/vite |@linaria/webpack4-loader | discontinued |@linaria/webpack5-loader | @wyw-in-js/webpack-loader There is no longer a need to install `@linaria/shaker` as it is now part of `@wyw-in-js/transform`, which will be installed automatically with the bundler plugins. The configuration file has been renamed from `linaria.config.js` (`linariarc`) to `wyw-in-js.config.js` (`.wyw-in-jsrc`). ## For Custom Processor Developers Base classes for processors and most helpers have been moved to `@wyw-in-js/processor-utils`. All APIs that had `linaria` in their names have been renamed: - The field that stores meta information in runtime has been renamed from `__linaria` to `__wyw_meta` - The export with all interpolated values has been renamed from `__linariaPreval` to `__wywPreval` - The caller name in Babel has been renamed from `linaria` to `wyw-in-js` For additional information, please visit the [wyw-in-js.dev](https://wyw-in-js.dev). # 4.x, 3.x from 2.x This release was mostly a refactor to [split into more packages](https://github.com/callstack/linaria/pull/687/). ## Breaking changes All these package imports in code need to be updated: | Old | New | --- | --- |linaria | @linaria/core |linaria/loader | @linaria/webpack4-loader, @linaria/webpack5-loader |linaria/react | @linaria/react |linaria/rollup | @linaria/rollup |linaria/server | @linaria/server |linaria/stylelint-config | @linaria/stylelint The `shaker` evaluator has moved from `linaria/evaluators` into its own package. You'll need to add `@linaria/shaker` to your package.json even if you never import it. The Babel preset moved from `linaria/babel` to `@linaria/babel-preset` but has to be referenced as `@linaria` in a Babel config. See https://github.com/callstack/linaria/issues/704 In package.json import all the new packages you use. # 2.x from 1.x ## Breaking changes ### `Core-js` dependency removal and _theoretical_ drop compatibility for `node` below `10` In [#569](https://github.com/callstack/linaria/pull/569) We removed `core-js` dependency. It should not effectively affect your users or build pipelines. But it was technically a breaking change. We set babel preset that makes all non-browser dependencies compatible with `node` from version `10`. But previous setup was using `browser` env so If you was able to build Linaria with previous versions of node, it should work also now. Support for browsers environment didn't change. After that you should be able to solve issues with `core-js` dependency in your project, because it will no longer collide with version used by Linaria. ### The default [evaluation strategy](./HOW_IT_WORKS.md#evaluators) has been changed to `shaker` It should not affect existed code since the new strategy is more powerful, but you can always switch to the old one by adding the next `rules` section to your Linaria-config: ```js [ { action: require('linaria/evaluators').extractor, }, { test: /\/node_modules\//, action: 'ignore', }, ] ``` --- # Linaria Documentation # Source: https://raw.githubusercontent.com/callstack/linaria/master/docs/THEMING.md # Path: docs/THEMING.md # Theming There are several approaches you can use for theming. Depending on the browser support and requirements, you can pick the approach that suits you the best. ## CSS custom properties CSS custom properties aka CSS variables are one of the best ways to apply a theme to your web app. The basic concept is that we add a class name to represent the theme to our root element, and use different values for our CSS variables based on the theme: ```js // Create class names for different themes const a = css` --color-primary: #6200ee; --color-accent: #03dac4; `; const b = css` --color-primary: #03a9f4; --color-accent: #e91e63; `; // Apply a theme to the root element ; ``` Now, we can use these variables in any of the child elements: ```js const Button = styled.button` background-color: var(--color-accent); `; ``` CSS custom properties are [not supported in some browsers such as IE](http://caniuse.com/#feat=css-variables), so if you need to support those browsers, this is not a viable approach. ## Class names Another approach is to add a class name representing the theme (e.g. - `theme-dark`) in the root element, and take advantage of CSS child selectors to theme the elements based on this parent class name. For example, let's add the theme to the root component: ```js ``` Now, we can conditionally style any child element according to the theme: ```js const Header = styled.h1` text-transform: uppercase; .theme-dark & { color: white; } .theme-light & { color: black; } `; ``` You could even make some helpers to make writing this easier: ```js // Put your colors in an object grouped by the theme names const colors = { light: { text: 'black', }, dark: { text: 'white', }, }; // Create a small helper function to loop over the themes and create CSS rule sets const theming = cb => Object.keys(colors).reduce((acc, name) => Object.assign(acc, { [`.theme-${name} &`]: cb(colors[name]), }), {}); // Use the helper in your styles const Header = styled.h1` text-transform: uppercase; ${theming(c => ({ color: c.text, }))}; `; ``` This approach works in all browsers, and is the best approach if you want to support older browsers without support for CSS custom properties. ## React Context Another approach is to use React Context to pass down colors, and then use function interpolations with the `styled` tag to use the colors in your component. You could use something like [`@callstack/react-theme-provider`](https://github.com/callstack/react-theme-provider) or write your own HOC. Then use it like: ```js const Button = withTheme(styled.button` background-color: ${props => props.theme.accent}; `); ``` Note that this approach also uses CSS custom properties under the hood since function interpolations compile down to CSS custom properties. So the browser support is limited. --- # Linaria Documentation # Source: https://raw.githubusercontent.com/callstack/linaria/master/README.md # Path: README.md Linaria

Zero-runtime CSS in JS library.

--- [![Build Status][build-badge]][build] [![Code Coverage][coverage-badge]][coverage] [![Version][version-badge]][package] [![MIT License][license-badge]][license] [![All Contributors][all-contributors-badge]](#contributors) [![PRs Welcome][prs-welcome-badge]][prs-welcome] [![Chat][chat-badge]][chat] [![Code of Conduct][coc-badge]][coc] [![Greenkeeper][greenkeeper-badge]][greenkeeper] [![Sponsored by Callstack][callstack-badge]][callstack] [![tweet][tweet-badge]][tweet] ## Features - Write CSS in JS, but with **zero runtime**, CSS is extracted to CSS files during build - Familiar **CSS syntax** with Sass like nesting - Use **dynamic prop based styles** with the React bindings, uses CSS variables behind the scenes - Easily find where the style was defined with **CSS sourcemaps** - **Lint your CSS** in JS with [stylelint](https://github.com/stylelint/stylelint) - Use **JavaScript for logic**, no CSS preprocessor needed - Optionally use any **CSS preprocessor** such as Sass or PostCSS - Supports **atomic styles** with `@linaria/atomic` **[Why use Linaria](/docs/BENEFITS.md)** **[Learn how Airbnb improved both developer experience and web performance with Linaria](https://medium.com/airbnb-engineering/airbnbs-trip-to-linaria-dc169230bd12)** ## Installation ```sh npm install @linaria/core @linaria/react @wyw-in-js/babel-preset ``` or ```sh yarn add @linaria/core @linaria/react @wyw-in-js/babel-preset ``` ## Setup Linaria is now built on top of [wyw-in-js.dev](https://wyw-in-js.dev/). It supports various bundlers to extract the CSS at build time. To configure your bundler, check the following guides on the wyw-in-js.dev site: - [webpack](https://wyw-in-js.dev/bundlers/webpack) - [esbuild](https://wyw-in-js.dev/bundlers/esbuild) - [Rollup](https://wyw-in-js.dev/bundlers/rollup) - [Vite](https://wyw-in-js.dev/bundlers/vite) - [Svelte](https://wyw-in-js.dev/bundlers/svelte) See [Configuration](https://wyw-in-js.dev/configuration) to customize how Linaria processes your files. ## Syntax Linaria can be used with any framework, with additional helpers for React. The basic syntax looks like this: ```js import { css } from '@linaria/core'; import { modularScale, hiDPI } from 'polished'; import fonts from './fonts'; // Write your styles in `css` tag const header = css` text-transform: uppercase; font-family: ${fonts.heading}; font-size: ${modularScale(2)}; ${hiDPI(1.5)} { font-size: ${modularScale(2.5)}; } `; // Then use it as a class name

Hello world

; ``` You can use imported variables and functions for logic inside the CSS code. They will be evaluated at build time. If you're using [React](https://reactjs.org/), you can use the `styled` helper, which makes it easy to write React components with dynamic styles with a styled-component like syntax: ```js import { styled } from '@linaria/react'; import { families, sizes } from './fonts'; // Write your styles in `styled` tag const Title = styled.h1` font-family: ${families.serif}; `; const Container = styled.div` font-size: ${sizes.medium}px; color: ${props => props.color}; border: 1px solid red; &:hover { border-color: blue; } ${Title} { margin-bottom: 24px; } `; // Then use the resulting component Hello world ; ``` Dynamic styles will be applied using CSS custom properties (aka CSS variables) and don't require any runtime. See [Basics](/docs/BASICS.md) for a detailed information about the syntax. ## Demo [![Edit Linaria Demo](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/linaria-react-vite-ts-qyj5xd) ## Documentation - [Basics](/docs/BASICS.md) - [API and usage](/docs/API.md) - [Client APIs](/docs/API.md#client-apis) - [Server APIs](/docs/API.md#server-apis) - [Configuration](/docs/CONFIGURATION.md) - [Dynamic styles with `css` tag](/docs/DYNAMIC_STYLES.md) - [Theming](/docs/THEMING.md) - [Critical CSS extraction](/docs/CRITICAL_CSS.md) - [Bundlers integration](/docs/BUNDLERS_INTEGRATION.md) - [webpack](/docs/BUNDLERS_INTEGRATION.md#webpack) - [Rollup](/docs/BUNDLERS_INTEGRATION.md#rollup) - [CLI](/docs/CLI.md) - [Linting](/docs/LINTING.md) - [How it works](/docs/HOW_IT_WORKS.md) - [Example](/website) ## Contributing We appreciate any support in library development! Take a look on [Contributing](CONTRIBUTING.md) docs to check how you can run Linaria in development mode. ## Trade-offs - No IE11 support when using dynamic styles in components with `styled`, since it uses CSS custom properties - Dynamic styles are not supported with `css` tag. See [Dynamic styles with `css` tag](/docs/DYNAMIC_STYLES.md) for alternative approaches. - Modules used in the CSS rules cannot have side-effects. For example: ```js import { css } from '@linaria/core'; import colors from './colors'; const title = css` color: ${colors.text}; `; ``` Here, there should be no side-effects in the `colors.js` file, or any file it imports. We recommend to move helpers and shared configuration to files without any side-effects. ## Interoperability with other CSS-in-JS libraries Linaria can work together with other CSS-in-JS libraries out-of-the-box. However, if you want to use styled components from Linaria as selectors in `styled-components`/`emotion`, you need to use [@linaria/interop](/packages/interop/README.md) ## Editor Plugins ### VSCode - Syntax Highlighting - [language-babel](https://marketplace.visualstudio.com/items?itemName=mgmcdermott.vscode-language-babel) - Autocompletion - [vscode-styled-components](https://marketplace.visualstudio.com/items?itemName=styled-components.vscode-styled-components) - Linting - [stylelint](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint) ### Atom - Syntax Highlighting and Autocompletion - [language-babel](https://atom.io/packages/language-babel) ### Webstorm - Syntax Highlighting & Autocompletion - [webstorm-styled-components](https://github.com/styled-components/webstorm-styled-components) ### Sublime Text - Syntax Highlighting & Autocompletion - [Naomi](https://packagecontrol.io/packages/Naomi), [JSCustom](https://packagecontrol.io/packages/JSCustom) (refer to document on how to turn on Styled Component syntax) - Linting - [SublimeLinter-stylelint](https://packagecontrol.io/packages/SublimeLinter-stylelint), [LSP Stylelint](https://packagecontrol.io/packages/LSP-stylelint) ## Recommended Libraries - [gatsby-plugin-linaria](https://github.com/cometkim/gatsby-plugin-linaria) – Gatsby plugin that sets up Babel and webpack configuration for Linaria. - [polished.js](https://polished.js.org/) - A lightweight toolset for writing styles in JavaScript. - [craco-linaria](https://github.com/jedmao/craco-linaria) - A [Craco](https://www.npmjs.com/package/@craco/craco) plugin that allows you to use Linaria [without ejecting](https://create-react-app.dev/docs/alternatives-to-ejecting) from a [CRA](https://create-react-app.dev/). ## Inspiration - [glam](https://github.com/threepointone/glam) - [styled-components](https://github.com/styled-components/styled-components) - [css-literal-loader](https://github.com/4Catalyzer/css-literal-loader) ## Acknowledgements This project wouldn't have been possible without the following libraries or the people behind them. - [babel](https://babeljs.io/) - [stylis.js](https://github.com/thysultan/stylis.js) Special thanks to [@kentcdodds](https://github.com/kentcdodds) for his babel plugin and [@threepointone](https://github.com/threepointone) for his suggestions and encouragement. ## Made with ❤️ at Callstack Linaria is an open source project and will always remain free to use. If you think it's cool, please star it 🌟. [Callstack](https://callstack.com) is a group of React and React Native geeks, contact us at [hello@callstack.com](mailto:hello@callstack.com) if you need any help with these or just want to say hi! Like the project? ⚛️ [Join the team](https://callstack.com/careers/?utm_campaign=Senior_RN&utm_source=github&utm_medium=readme) who does amazing stuff for clients and drives React Native Open Source! 🔥 ## Sponsors

{callstack}

Servers.com

## Contributors Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)):
Paweł Trysła
Paweł Trysła

💻 📖 🤔
Satyajit Sahoo
Satyajit Sahoo

💻 📖 🤔
Michał Pierzchała
Michał Pierzchała

💻 📖 🤔
Lucas
Lucas

📖
Alexey Pronevich
Alexey Pronevich

📖
Wojtek Szafraniec
Wojtek Szafraniec

💻
Anton Evzhakov
Anton Evzhakov

💻 🤔 📖
Tushar Sonawane
Tushar Sonawane

📖 💡
Ferran Negre
Ferran Negre

📖
Jakub Beneš
Jakub Beneš

💻 📖
Oscar Busk
Oscar Busk

🐛 💻
Dawid
Dawid

💻 📖
Kacper Wiszczuk
Kacper Wiszczuk

💻 📖
Denis Rul
Denis Rul

💻
Johan Holmerin
Johan Holmerin

💻 📖
Gilad Peleg
Gilad Peleg

📖
Giuseppe
Giuseppe

💻
Matija Marohnić
Matija Marohnić

💻 📖
Stefan Schult
Stefan Schult

💻
Ward Peeters
Ward Peeters

💻
radoslaw-medryk
radoslaw-medryk

💻
杨兴洲
杨兴洲

💻
Dawid Karabin
Dawid Karabin

📖
Chris Abrams
Chris Abrams

💻 📖 🤔
Jayphen
Jayphen

💻
c4605
c4605

💻
Toru Kobayashi
Toru Kobayashi

💻
Jakub Mazurek
Jakub Mazurek

💻
Joshua Nelson
Joshua Nelson

💻 🤔 📖
Tomasz Krzyżowski
Tomasz Krzyżowski

💻
Martin Schulze
Martin Schulze

💻
wmzy
wmzy

💻
Hyeseong Kim
Hyeseong Kim

💻
Martin Hochel
Martin Hochel

💻
Daniel Lo Nigro
Daniel Lo Nigro

💻
0xflotus
0xflotus

💻
Afzal Sayed
Afzal Sayed

💻
AijiUejima
AijiUejima

💻
Oleksii Vasyliev
Oleksii Vasyliev

💻
Alican Erdoğan
Alican Erdoğan

💻
Aman Kubanychbek
Aman Kubanychbek

💻
Andrew Gerard
Andrew Gerard

💻
Andrey Frolov
Andrey Frolov

💻
Benjamin Solum
Benjamin Solum

💻
Billy Kwok
Billy Kwok

💻
Christian Todd
Christian Todd

💻
David Peek
David Peek

💻
Denis Skiba
Denis Skiba

💻
Dima Kharitonov
Dima Kharitonov

💻
Gabriel Valfridsson
Gabriel Valfridsson

💻
Gitai
Gitai

💻
Hampus Kraft
Hampus Kraft

💻
Igor Sukharev
Igor Sukharev

💻
Ikko Ashimine
Ikko Ashimine

💻
Iman Mohamadi
Iman Mohamadi

💻
JB <codecorsair>
JB

💻
Jack Works
Jack Works

💻
James George
James George

💻
Jed Mao
Jed Mao

💻
Joe Lencioni
Joe Lencioni

💻
Joey Cozza
Joey Cozza

💻
Juan Ferreras
Juan Ferreras

💻
Kazuma Ebina
Kazuma Ebina

💻
Lars Kappert
Lars Kappert

💻
Luciano Mammino
Luciano Mammino

💻
Madhav Varshney
Madhav Varshney

💻
Malash
Malash

💻
Martijn Swaagman
Martijn Swaagman

💻
Matias Lahti
Matias Lahti

💻
Michael James
Michael James

💻
Michael Strobel
Michael Strobel

💻
Michał Chudziak
Michał Chudziak

💻
Mike
Mike

💻
Mike Stop Continues
Mike Stop Continues

💻
Mokshit Jain
Mokshit Jain

💻
Oleksandr Fediashov
Oleksandr Fediashov

💻
Paddy O'Brien
Paddy O'Brien

💻
Patrik Smělý
Patrik Smělý

💻
Pavel Udaloff
Pavel Udaloff

💻
Przemysław Bitkowski
Przemysław Bitkowski

💻
RiN
RiN

💻
Roman Sokhan
Roman Sokhan

💻
Seokmin Hong (Ray)
Seokmin Hong (Ray)

💻
Serge K Lebedev
Serge K Lebedev

💻
Sergey Korovin
Sergey Korovin

💻
Shreyas Sreenivas
Shreyas Sreenivas

💻
Sky Wickenden
Sky Wickenden

💻
Stanislav Panferov
Stanislav Panferov

💻
Ted Jenkins
Ted Jenkins

💻
Thanh Tran
Thanh Tran

💻
Thor Amorim
Thor Amorim

💻
tobenna
tobenna

💻
Tomas Carnecky
Tomas Carnecky

💻
Tsubasa1218
Tsubasa1218

💻
Turadg Aleahmad
Turadg Aleahmad

💻
Vitor Buzinaro
Vitor Buzinaro

💻
Mistereo
Mistereo

💻
Vladislav Kozulya
Vladislav Kozulya

💻
Yuhei Yasuda
Yuhei Yasuda

💻
Danil Kamyshov
Danil Kamyshov

💻
Sebastian Landwehr
Sebastian Landwehr

💻
everdimension
everdimension

💻
ptol
ptol

💻
roottool
roottool

💻
ryamaguchi0220
ryamaguchi0220

💻
simka
simka

💻
soso
soso

💻
Nikita Skovoroda
Nikita Skovoroda

💻
黄小健
黄小健

💻
iMoses
iMoses

💻
Jeremy Neander
Jeremy Neander

💻
Andy Parsons
Andy Parsons

💻
Platane
Platane

📖
Tim Kutnick
Tim Kutnick

📖
Dmitrii Pikulin
Dmitrii Pikulin

💻
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome! [build-badge]: https://img.shields.io/circleci/project/github/callstack/linaria/master.svg?style=flat-square [build]: https://circleci.com/gh/callstack/linaria [coverage-badge]: https://img.shields.io/codecov/c/github/callstack/linaria.svg?style=flat-square [coverage]: https://codecov.io/github/callstack/linaria [version-badge]: https://img.shields.io/npm/v/linaria.svg?style=flat-square [package]: https://www.npmjs.com/package/linaria [license-badge]: https://img.shields.io/npm/l/linaria.svg?style=flat-square [license]: https://opensource.org/licenses/MIT [prs-welcome-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square [prs-welcome]: https://github.com/callstack/linaria/blob/master/CONTRIBUTING.md [coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square [coc]: https://github.com/callstack/linaria/blob/master/CODE_OF_CONDUCT.md [all-contributors-badge]: https://img.shields.io/badge/all_contributors-23-orange.svg?style=flat-square [chat-badge]: https://img.shields.io/discord/426714625279524876.svg?style=flat-square&colorB=758ED3 [chat]: https://discord.gg/zwR2Cdh [tweet-badge]: https://img.shields.io/badge/tweet-%23linaria-blue.svg?style=flat-square&colorB=1DA1F2&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAUCAYAAACXtf2DAAAAAXNSR0IArs4c6QAAAaRJREFUOBGtlM8rBGEYx3cWtRHJRaKcuMtBSitxkCQ3LtzkP9iUUu5ODspRHLhRLtq0FxeicEBC2cOivcge%2FMgan3fNM8bbzL4zm6c%2BPT%2Fe7%2FO8887svrFYBWbbtgWzsAt3sAcpqJFxxF1QV8oJFqFPFst5dLWQAT87oTgPB7DtziFRT1EA4yZolsFkhwjGYFRO8Op0KD8HVe7unoB6PRTBZG8IctAmG1xrHcfkQ2B55sfI%2ByGMXSBqV71xZ8CWdxBxN6ThFuECDEAL%2Bc9HIzDYumVZ966GZnX0SzCZvEqTbkaGywkyFE6hKAsBPhFQ18uPUqh2ggJ%2BUor%2F4M%2F%2FzOC8g6YzR1i%2F8g4vvSI%2ByD7FFNjexQrjHd8%2BnjABI3AU4Wl16TuF1qANGll81jsi5qu%2Bw6XIsCn4ijhU5FmCJpkV6BGNw410hfSf6JKBQ%2FUFxHGYBnWnmOwDwYQ%2BwzdHqO75HtiAMJfaC7ph32FSRJCENUhDHsLaJkL%2FX4wMF4%2BwA5bgAcrZE4sr0Cu9Jq9fxyrvBHWbNkMD5CEHWTjjT2m6r5D92jfmbbKJEWuMMAAAAABJRU5ErkJggg%3D%3D [tweet]: https://twitter.com/intent/tweet?text=Check%20out%20linaria!%20https://github.com/callstack/linaria%20%F0%9F%91%8D [greenkeeper-badge]: https://badges.greenkeeper.io/callstack/linaria.svg [greenkeeper]: https://greenkeeper.io/ [callstack-badge]: https://callstack.com/images/callstack-badge.svg [callstack]: https://callstack.com/open-source/?utm_source=github.com&utm_medium=referral&utm_campaign=linaria&utm_term=readme