Hi everyone! My name is Alex. I’m one of the founders and lead developer at Quarkly. In this post, I’d like to share with you how the concept of atomic CSS, which we follow, together with the disadvantages of styled-system functionality (and rebass in particular) inspired us to create our own tool that we call Atomize.
Our Quarkly project is a mix of a graphic editor (like Figma and Sketch) and website builder (similar to Webflow), complemented by features of traditional IDE. We’ll be sure to elaborate on Quarkly in a separate post, as there is plenty to tell and show, but today we’ll focus on the details of the Atomize tool.
Atomize is the heart of the whole project, as it allows us to solve tasks that would be difficult or even impossible to handle using styled-system and rebass. At the very least, the latter solution is much less elegant.
If you don’t have time to read the entire post now, check out a brief description of Atomize on our GitHub.
And to make your introduction to our tool even more fun, we are launching a contest to build React components using Atomize. You can find out more at the end of this post.
When we got down to developing this tool, our team’s task was to give users the opportunity to code on two components, but without the need to have a separate CSS file. This was to keep the code as minimalistic as possible while retaining all CSS features in contrast to inline styles.
The task was far from ground-breaking and, at first sight, could be easily solved with the help of styled-system (and rebass). But its functionality turned out to be limited for us. Or rather, we ran into the following problems:
- inconvenient breakpoints
- no option to write styles for hover, focus, and other behaviors
- mechanism for working with themes wasn’t as flexible as we needed
- minimalistic interface
- option to use variables from the theme in composite CSS properties
- support for hover and any other pseudo-classes
- short aliases for each property (like in emmet)
- opportunity to set styles for a specific breakpoint, all while keeping the markup readable
That being said, Atomize is intended for two main purposes:
- creation of components that support atomic CSS and themes
- creation of widgets for the interactive editing in the Quarkly project
Before you start working with Atomize, you need to set up dependencies:
Atomize serves as a wrapper around a styled-component and has a similar API.
Just call the method using the name of the required element:
As a result, we get the React component that can take any CSS in the form of properties.
To make it easier to use, we developed the system of alias properties. For example, bgc === backgroundColor
To see the full list of properties and aliases, follow this link.
Plus, we added the mechanism of inheritance in React:
This, I think, should be explained in more detail.
Quarkly themes are based on CSS variables. The key feature of Quarkly themes is that variables from themes can be reused both in props and themes. You don’t need to use additional abstractions, like template functions, and no additional editing is needed by the user.
To use variables from a theme, just describe the property in the theme and call this property using the prefix "--".
The variables can be used both in JSX:
(The color #04080C is available through the --colors-dark property)
And in the theme itself:
(We reused a variable from the colors by including it in the borders theme)
The shorter syntax is used for colors in the JSX markup:
Themes have breakpoints for working with media expressions.
Any property can be prefixed with a breakpoint key name.
You can find the source code here.
The main difference between Atomize and the styled system is the "effects".
What are they and why do you need them?
Well, imagine you create a Button component, change its color and border and then… you realize you don’t know how to assign styles to hover, focus, etc. This is where effects come to the rescue.
When creating a component, just transfer an object with the configuration:
The key is the prefix in the name of the property, and the value is a CSS selector. This is the same way we implemented pseudo-classes.
Now, if you specify the hover prefix for any CSS property, it will be applied to a certain effect. For example, when you mouse over it:
You can also combine effects with media expressions:
Let's build several interesting components to illustrate the features I’ve described above.
Here are two examples:
- a simple component that shows all the capabilities of the library
- a more complex example with a Pokémon card
Everybody loves Pokémon, don’t they? :)
In the second example, we used most of the functionality, as well as the external API.
The second purpose of Atomize, as I mentioned above, is to create widgets in Quarkly based on custom React components.
All you have to do is wrap your component in Atomize and describe its configuration so that Quarkly can understand which properties can be interactively edited:
The configuration fields for the component look like this:
- effects – defines browser pseudo-classes (hover, focus, etc.)
- description – component description that will appear when you mouse over its name
- propInfo – configuration of controls that will be displayed on the right panel (Props tab)
How to specify the props to be displayed on the right panel (Props tab):
Possible control options:
One more example, where we’ve added our custom component to the system and can now edit it interactively:
We put our heads together and decided there’s no better way to fuel the community's interest in our Atomize tool than by following a path that’s as simple and logical as Atomize itself — a contest!
All information about the deadline, rules and prizes is available on the official contest website.
But in short: to enter and win, you need to come up with a new (or find an existing) interesting and useful component and adapt it to Atomize requirements. And if your component gets added to Quarkly, you can count on some extra prizes from the team :)