Zero-runtime CSS in JS library.
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
- Use JavaScript for logic, no CSS preprocessor needed
- Optionally use any CSS preprocessor such as Sass or PostCSS
Installation
npm install @linaria/core @linaria/react @linaria/babel-preset @linaria/shaker
or
yarn add @linaria/core @linaria/react @linaria/babel-preset @linaria/shaker
Setup
Linaria currently supports webpack and Rollup to extract the CSS at build time. To configure your bundler, check the following guides:
Or configure Linaria with one of the following integrations:
Optionally, add the @linaria
preset to your Babel configuration at the end of the presets list to avoid errors when importing the components in your server code or tests:
{
"presets": [
"@babel/preset-env",
"@babel/preset-react",
"@linaria"
]
}
See 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:
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
<h1 className={header}>Hello world</h1>;
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, you can use the styled
helper, which makes it easy to write React components with dynamic styles with a styled-component like syntax:
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
<Container color="#333">
<Title>Hello world</Title>
</Container>;
Dynamic styles will be applied using CSS custom properties (aka CSS variables) and don't require any runtime.
See Basics for a detailed information about the syntax.
Demo
Documentation
- Basics
- API and usage
- Configuration
- Dynamic styles with
css
tag - Theming
- Critical CSS extraction
- Bundlers integration
- CLI
- Linting
- How it works
- Example
Contributing
We appreciate any support in library development!
Take a look on Contributing 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 withcss
tag for alternative approaches. -
Modules used in the CSS rules cannot have side-effects. For example:
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
Editor Plugins
VSCode
- Syntax Highlighting - language-babel
- Autocompletion - vscode-styled-components
- Linting - stylelint
Atom
- Syntax Highlighting and Autocompletion - language-babel
Webstorm
- Syntax Highlighting & Autocompletion - webstorm-styled-components
Sublime Text
- Syntax Highlighting & Autocompletion - Naomi, JSCustom (refer to document on how to turn on Styled Component syntax)
- Linting - SublimeLinter-stylelint, LSP Stylelint
Recommended Libraries
- gatsby-plugin-linaria – Gatsby plugin that sets up Babel and webpack configuration for Linaria.
- polished.js - A lightweight toolset for writing styles in JavaScript.
- craco-linaria - A Craco plugin that allows you to use Linaria without ejecting from a CRA.
Inspiration
Acknowledgements
This project wouldn't have been possible without the following libraries or the people behind them.
Special thanks to @kentcdodds for his babel plugin and @threepointone for his suggestions and encouragement.
❤️
at Callstack
Made with Linaria is an open source project and will always remain free to use. If you think it's cool, please star it
Like the project?
Contributors
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!
new styles extractor
Summary
This is a PoC of more advanced styles extractor. It can evaluate almost any js code whereas current extractor has problems with code like this:
Unlike current implementation, this extractor does not evaluate expressions immediately in
TaggedTemplateExpression
visitor but collects them for later evaluation. Then it builds a dependency graph for all expressions and strips all unrelated code from a module. On the last stage, it does a batch evaluation of all expressions.I've created this PR in WIP stage because I had a bit painful merge after 1.3.1 release and I also found your typescript branch :) So if you like it I will do some refactoring and rewrite to TS.
Test plan
New tests were added, old tests still work except one test with invalid code and two tests that check dependency extraction during evaluation.
Add an option to output atomic css
Do you want to request a feature or report a bug? Feature
What is the current behavior?
If the current behavior is a bug, please provide the steps to reproduce and a minimal repository on GitHub that we can
yarn install
andyarn test
.What is the expected behavior? The current behavior is
Please provide your exact Babel configuration and mention your Linaria, Node, Yarn/npm version and operating system.
Update website and readme with logo
We need it, sooner or later. Already asked my designer-brother (@pierzchala) to work on it in his free time (may be in couple of weeks).
The logo should resemble concepts like
flower
,CSS
,JS
.Styling custom components with NextJs
I'm using NextJs with linaria and trying to apply styled on custom component:
and get error:
Not compatible with Webpack file and url loaders?
Do you want to request a feature or report a bug? Bug.
What is the current behavior? Webpack’s
file-loader
orurl-loader
(they come standard withcreate-react-app
) let yourequire()
(orimport
) any file type (like images and fonts). At build time, therequire
statement gets replaced with a URL that you can use to load the file at runtime. Unfortunately Linaria seems to break any time I reference anything that gets loaded this way. It appears to attempt to load the file as if it were a JS module. E.g. both of these fail:If the current behavior is a bug, please provide the steps to reproduce and a minimal repository on GitHub that we can
yarn install
andyarn test
. Quickcreate-react-app
that attempts to load an SVG and a web font on the home page: https://github.com/steadicat/linaria-testWhat is the expected behavior? Expected behavior is for Linaria to let the loader run first so that those
require
s become plains strings to be included in the CSS.Please provide your exact Babel configuration and mention your Linaria, Node, Yarn/npm version and operating system. See app above.
Rollup: Using the "styled" tag in runtime is not supported
Environment
rollup
:^1.2.2
linaria
:^1.3.1
Description
Project is TypeScript + Linaria transpiled via Babel using
@babel/preset-typescript
. The module bundler I am using isrollup
. Despite having included thelinaria/babel
preset in mybabel.config.js
file I am still seeing an error in the console:Error: Using the "styled" tag in runtime is not supported. Make sure you have set up the Babel plugin correctly.
Reproducible Demo
[1.4.0-beta.0] A build error
This problem was reported by @Guria (#495)
Environment
Description
Reproducible Demo
Error: Cannot find module 'core-js/modules/es6.regexp.to-string'
I ran this example on my computer and I got this error:
ERROR in ./src/App.js Module build failed (from ./node_modules/linaria/loader.js): Error: Cannot find module 'core-js/modules/es6.regexp.to-string' at Function.Module._resolveFilename (internal/modules/cjs/loader.js:613:15) at Function.Module._load (internal/modules/cjs/loader.js:539:25) at Module.require (internal/modules/cjs/loader.js:667:17) at require (internal/modules/cjs/helpers.js:20:18) at Object.<anonymous> (/Users/egortrubnikov-panov/Downloads/linaria-demo 2/node_modules/linaria/lib/loader.js:3:1) at Module._compile (internal/modules/cjs/loader.js:738:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:749:10) at Module.load (internal/modules/cjs/loader.js:630:32) at tryModuleLoad (internal/modules/cjs/loader.js:570:12) at Function.Module._load (internal/modules/cjs/loader.js:562:3)
how can I fix this?
[website] Replace ESLint with Prettier
Do you want to request a feature or report a bug? Feature (Build tools)
What is the current behavior? ESLint rules are so annoying and slow down the development.
If the current behavior is a bug, please provide the steps to reproduce and a minimal repository on GitHub that we can
yarn install
andyarn test
. N/AWhat is the expected behavior? Prettier is the standard currently and so many popular projects use it and makes you write the code without being worried about one less semicolon or on which line close which tag :(
Please provide your exact Babel configuration and mention your Linaria, Node, Yarn/npm version and operating system. Not related.
Fix dual packages ES module import bug
Fixes #904 (and possibly #1043)
Solution is based on this documentation: https://nodejs.org/api/packages.html#approach-1-use-an-es-module-wrapper
It properly configures the package entry point for both CommonJS and ESM, which is currently not the case (see #904)
EvalError: Unexpected token 'export' in
Environment
Description
Seems related to babel doing a transform it shouldn't?
Reproducible Demo
https://github.com/ntucker/anansi/pull/1591
fix: preeval emits invalid code
Fix some instances where preeval emits invalid code.
Motivation
Avoid breaking builds due to buggy preeval logic.
Summary
Unfortunately, babel seems to record identifiers as globals even when they're accessed via TS type references, e.g:
will result in
scope.hasGlobal('fetch')
returning true. preeval will end up deleting the class property, and then the entire class. The same applies iffetch
is accessed in a member expression, e.gThe key is the
typeof global.fetch
messes up Babel's scope tracking, which makes subsequentisGlobal/isBrowserGlobal
checks invalid.A similar problem occurs with TS type references - accessing
window.foo
orglobal.foo
will break the scope tracking, resulting in TS type references that look like globals getting deleted. See the unit test for an example.Test plan
Added unit tests
fix: exports.hasOwnProperty is not a function
The Proxy for
this.#exports
did not forward unknown properties to the underlying Object instance.Motivation
Fixes issues like https://github.com/callstack/linaria/issues/1140
Summary
Ensure that the Proxy for this.#exports forwards unknown properties to the underlying Object instance.
Test plan
Added a unit test.
[Release request] Release v3 minor version with atomic styled support
Describe the feature
Release a v3.1 (or whatever minor version is preferred) containing the
styled
atomic support in https://github.com/callstack/linaria/pull/966, without the changes in 3.0.0-beta.19.Motivation
I work with @jpnelson and we're currently running Linaria with atomic styles on 3.0.0-beta.18, which has been stable and working well for us over the past 6 months or so. We'd like to use the
styled
atomic support contributed by @juanferreras in https://github.com/callstack/linaria/pull/966, but it was never published to NPM. Instead, 3.0.0-beta.19 was released, which contains a major refactor to how tags are resolved, and also removes thelibResolver
option[^1] that was contributed in https://github.com/callstack/linaria/issues/851. v4 contains even bigger changes and we've run into several issues with shaker/preeval on our codebase, so we'd like to hold off on those upgrades for now.I'll be putting up several PRs for issues we found while testing a v4 upgrade, so hopefully we can get up to date later this year!
[^1]: We're using libResolver as a way to enable atomic styles across our codebase without needing to make code changes (via swapping
@linaria/core
and@linaria/atomic
imports).Possible implementations
Cut a release at this revision: https://github.com/callstack/linaria/commit/f59860b09c5f91b0423dbf188e5f8aaaef38a6b5
@linaria/babel-preset deletes code unexpectedly
Environment
Description
We use
@linaria/babel
in server builds to ensure that server side rendering (e.g ReactDOMServer.renderToString) produces the same classnames as the browser build. However, it appears that this babel transform also deletes exports unexpectedly if they are referenced in thecss
template literal.I believe the root cause is the fact that
processTemplateExpression
will inject a__linariaPreval
export as well as various temporary_exp
variables. Linaria tries to clean them up: https://github.com/callstack/linaria/blob/3ce985e0f7448dca4299adcd90c3f8bb5c6197e4/packages/babel/src/plugins/babel-transform.ts#L77-L83but
removeWithRelated
appears to have a bug where it's deleting exports.The same bug happens when using the
transform
method exported by@linaria/babel-preset
, due to the similar code here: https://github.com/callstack/linaria/blob/3ce985e0f7448dca4299adcd90c3f8bb5c6197e4/packages/babel/src/plugins/collector.ts#L55-L61In general this approach of mutating the input file to add and remove Linaria temporary variables feels like a bad idea; the only modifications that Linaria makes to the input ought to be replacing tags.
Reproducible Demo
https://codesandbox.io/p/sandbox/stupefied-hellman-r0kbh0?file=%2Finput.js&selection=%5B%7B%22endColumn%22%3A10%2C%22endLineNumber%22%3A8%2C%22startColumn%22%3A10%2C%22startLineNumber%22%3A8%7D%5D
Can V4 remove the configuration of babelOptions when using language features?
Describe the enhancement
The V3 doesn't require the babelOptions when using Vite with outbox TS language. V4 requires specifying the babel options, but I'm using Typescript decorators, which are different from the Babel decorators. I can't configure the decorator's features through babel options.
See this issue for details: https://github.com/babel/babel/issues/8864
Is there a possible enhancement for not configuring the babel options just like the V3 does?
Motivation
Using full featured Typescript decorators.
Possible implementations
Related Issues
All props are filtered out when using "as" props
Environment
Description
Linaria uses static mechanism to detect if the styled component should pass props https://github.com/callstack/linaria/pull/1101 However, when you use "as" prop the static mechanism is not working and component that you pass in "as" doesn't have props.
Reproducible Demo
https://codesandbox.io/s/linaria-as-iuhnl8?file=/src/App.tsx