preprocessors – CSS-Tricks https://css-tricks.com Tips, Tricks, and Techniques on using Cascading Style Sheets. Fri, 08 Oct 2021 17:14:08 +0000 en-US hourly 1 https://wordpress.org/?v=6.1.1 https://i0.wp.com/css-tricks.com/wp-content/uploads/2021/07/star.png?fit=32%2C32&ssl=1 preprocessors – CSS-Tricks https://css-tricks.com 32 32 45537868 Jekyll doesn’t do components? Liar! https://css-tricks.com/jekyll-doesnt-do-components-liar/ https://css-tricks.com/jekyll-doesnt-do-components-liar/#comments Fri, 08 Oct 2021 17:14:05 +0000 https://css-tricks.com/?p=353374 I like the pushback from Katie Kodes here. I’ve said in the past that I don’t think server-side languages haven’t quite nailed “building in components” as well as JavaScript has, but hey, this is a good point:

1. Any basic


Jekyll doesn’t do components? Liar! originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
I like the pushback from Katie Kodes here. I’ve said in the past that I don’t think server-side languages haven’t quite nailed “building in components” as well as JavaScript has, but hey, this is a good point:

1. Any basic fragment-of-HTML “component” you can define with JSX in a file and then cross-reference as <MyComponent key="value" />, you can just as easily define with Liquid in a file and cross-reference in Jekyll as {% include MyComponent.html key=value %}.

2. Any basic fragment-of-HTML “layout” you can define with JSX in a file and then cross-reference as <MyLayout>Hello, world</MyLayout>, you can just as easily define with Liquid in a file and then cross-reference in the front matter of a Jekyll template as layout: MyLayout.

Any HTML preprocessor that can do partials with local variables is pretty close to replicating the best of stateless JavaScript components. The line gets even blurrier with stuff like Eleventy Serverless that can build individual pages on the fly by hitting the URL of a cloud function.

To Shared LinkPermalink on CSS-Tricks


Jekyll doesn’t do components? Liar! originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/jekyll-doesnt-do-components-liar/feed/ 2 353374
imba https://css-tricks.com/imba/ https://css-tricks.com/imba/#comments Mon, 20 Sep 2021 19:13:36 +0000 https://css-tricks.com/?p=352283 It’s not every day you see a new processor for building websites that reinvents the syntax for HTML and CSS and JavaScript. That’s what imba is doing.

That’s an awful lot of vendor lock-in, but I guess if you get …


imba originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
It’s not every day you see a new processor for building websites that reinvents the syntax for HTML and CSS and JavaScript. That’s what imba is doing.

That’s an awful lot of vendor lock-in, but I guess if you get over the learning curve and it helps you build performant websites quickly, then it’s no different than picking any other stack of processing languages.

I would hope their ultimate goal is to compile to native apps across platforms, but if not, if a developer wants to learn an entirely new way to craft an app, they might as well pick Flutter. As far as I understand it, the Flutter syntax is also quite a learning curve, but if you build your app that way, it makes good on the promise that it runs natively across all the major native mobile and desktop platforms, including the web.

To Shared LinkPermalink on CSS-Tricks


imba originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/imba/feed/ 3 352283
xm https://css-tricks.com/xm/ https://css-tricks.com/xm/#comments Wed, 21 Oct 2020 14:37:57 +0000 https://css-tricks.com/?p=322788 This is a neat little HTML preprocessor from Giuseppe Gurgone. It has very few features, but one of them is HTML includes, which is something I continue to be baffled that HTML doesn’t support natively. There are loads of ways


xm originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
This is a neat little HTML preprocessor from Giuseppe Gurgone. It has very few features, but one of them is HTML includes, which is something I continue to be baffled that HTML doesn’t support natively. There are loads of ways to handle it. I think it’s silly that it’s been consistently needed for decades and HTML could evolve to support it but hasn’t. So anyway, enter another option for handling it.

https://twitter.com/giuseppegurgone/status/1305851405660549122

What is extra neat is that it’s not just includes, but templating with includes in a really clean way. If this was Nunjucks, they solve that by creating a template.njk like…

{% block header %}
  This is the default (overridable) header.
{% endblock %}
<footer>
  {% block footer %}
    This is the default (overridable) footer.
  {% endblock %}
</footer>

And then your actual pages use that template like…

{% extends "parent.html" %}
{% block footer %}
  Special footer for this page.
{% endblock %}

In xm, the syntax stays HTML-y, which is nice. So this template.html

<slot name="header"></slot>
<footer>
  <slot name="footer"></slot>
</footer>

…gets used on a page like this:

<import src="template.html">
  <fill name="header">Custom Header</fill>
  <fill name="footer">
    <p>Custom footer</p>
  </fill>
</import>

Very clean. The additional fact that you can arbitrarily chuck a <markdown> tag anywhere you want and use Markdown within it is extra handy.


xm originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/xm/feed/ 3 322788
What I Like About Writing Styles with Svelte https://css-tricks.com/what-i-like-about-writing-styles-with-svelte/ https://css-tricks.com/what-i-like-about-writing-styles-with-svelte/#comments Wed, 23 Oct 2019 14:22:14 +0000 https://css-tricks.com/?p=297067 There’s been a lot of well-deserved hype around Svelte recently, with the project accumulating over 24,000 GitHub stars. Arguably the simplest JavaScript framework out there, Svelte was written by Rich Harris, the developer behind Rollup. There’s a lot …


What I Like About Writing Styles with Svelte originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
There’s been a lot of well-deserved hype around Svelte recently, with the project accumulating over 24,000 GitHub stars. Arguably the simplest JavaScript framework out there, Svelte was written by Rich Harris, the developer behind Rollup. There’s a lot to like about Svelte (performance, built-in state management, writing proper markup rather than JSX), but the big draw for me has been its approach to CSS.

Single file components

​​

React does not have an opinion about how styles are defined
—React Documentation

​​​​

A UI framework that doesn’t have a built-in way to add styles to your components is unfinished.
—Rich Harris, creator of Svelte

In Svelte, you can write CSS in a stylesheet like you normally would on a typical project. You can also use CSS-in-JS solutions, like styled-components and Emotion, if you’d like. It’s become increasingly common to divide code into components, rather than by file type. React, for example, allows for the collocation of a components markup and JavaScript. In Svelte, this is taken one logical step further: the Javascript, markup and styling for a component can all exist together in a single `.svelte`​ file. If you’ve ever used single file components in Vue, then Svelte will look familiar.

// button.svelte
<style>
  button {
    border-radius: 0;
    background-color: aqua;
  }
</style>

<button>
  <slot/>
</button>

Styles are scoped by default

By default, styles defined within a Svelte file are scoped. Like CSS-in-JS libraries or CSS Modules, Svelte generates unique class names when it compiles to make sure the styles for one element never conflict with styles from another.

That means you can use simple element selectors like div and button in a Svelte component file without needing to work with class names. If we go back to the button styles in our earlier example, we know that a ruleset for <button> will only be applied to our <Button> component — not to any other HTML button elements within the page. If you were to have multiple buttons within a component and wanted to style them differently, you’d still need classes. Classes will also be scoped by Svelte.

The classes that Svelte generates look like gibberish because they are based on a hash of the component styles (e.g. svelte-433xyz). This is far easier than a naming convention like BEM. Admittedly though, the experience of looking at styles in DevTools is slightly worse as the class names lack meaning.

The markup of a Svelte component in DevTools.

It’s not an either/or situation. You can use Svelte’s scoped styling along with a regular stylesheet. I personally write component specific styles within .svelte files, but make use of utility classes defined in a stylesheet. For global styles to be available across an entire app — CSS custom properties, reusable CSS animations, utility classes, any ‘reset’ styles, or a CSS framework like Bootstrap — I suggest putting them in a stylesheet linked in the head of your HTML document.

It lets us create global styles

As we’ve just seen, you can use a regular stylesheet to define global styles. Should you need to define any global styles from within a Svelte component, you can do that too by using :global. This is essentially a way to opt out of scoping when and where you need to.

For example, a modal component may want to toggle a class to style the body element:

<style>
:global(.noscroll) {
  overflow: hidden;
}
</style>

Unused styles are flagged

Another benefit of Svelte is that it will alert you about any unused styles during compilation. In other words, it searches for places where styles are defined but never used in the markup.

Conditional classes are terse and effortless

If the JavaScript variable name and the class name is the same, the syntax is incredibly terse. In this example, I’m creating modifier props for a full-width button and a ghost button.

<script>
  export let big = false;
  export let ghost = false;
</script>

<style>
  .big {
    font-size: 20px;
    display: block;
    width: 100%;
  }
  
  .ghost {
    background-color: transparent;
    border: solid currentColor 2px;
  }
</style>    
    
<button class:big class:ghost>
  <slot/>
</button>

A class of ghost will be applied to the element when a ghost prop is used, and a class of big is applied when a big prop is used.

<script>
  import Button from './Button.svelte';
</script>

<Button big ghost>Click Me</Button>

Svelte doesn’t require class names and prop names to be identical.

<script>
  export let primary = false;
  export let secondary = false;
</script>

<button
  class:c-btn--primary={primary}
  class:c-btn--secondary={secondary}
  class="c-btn">
  <slot></slot>
</button>

The above button component will always have a c-btn class but will include modifier classes only when the relevant prop is passed in, like this:

<Button primary>Click Me</Button>

That will generate this markup:

<button class="c-btn c-btn--primary">Click Me</button>

Any number of arbitrary classes can be passed to a component with a single prop:

<script>
let class_name = '';
export { class_name as class };
</script>

<button class="c-btn {class_name}">
  <slot />
</button>

Then, classes can be used much the same way you would with HTML markup:

<Button class="mt40">Click Me</Button>

From BEM to Svelte

Let’s see how much easier Svelte makes writing styles compared to a standard CSS naming convention. Here’s a simple component coded up using BEM.

.c-card {
  border-radius: 3px;
  border: solid 2px;
}

.c-card__title {
  text-transform: uppercase;
}

.c-card__text {
  color: gray;
}

.c-card--featured {
  border-color: gold;
}

Using BEM, classes get long and ugly. In Svelte, things are a lot simpler.

<style>
div {
  border-radius: 3px;
  border: solid 2px;
}

h2 {
  text-transform: uppercase;
}

p {
  color: gray;
}

.featured {
  border-color: gold;
}
</style>

<div class:featured>
  <h2>{title}</h2>
  <p>
    <slot />
  </p>
</div>

It plays well with preprocessors

CSS preprocessors feels a lot less necessary when working with Svelte, but they can work perfectly alongside one another by making use of a package called Svelte Preprocess. Support is available for Less, Stylus and PostCSS, but here we’ll look at Sass. The first thing we need to do is to install some dependencies:

npm install -D svelte-preprocess node-sass

Then we need to import autoPreprocess in rollup.config.js at the top of the file.

import autoPreprocess from 'svelte-preprocess';

Next, let’s find the plugins array and add preprocess: autoPreprocess() to Svelte:

export default {
  plugins: [
    svelte({
      preprocess: autoPreprocess(),
      ...other stuff

Then all we need to do is specify that we’re using Sass when we’re working in a component file, using type="text/scss" or lang="scss" to the style tag.

<style type="text/scss">
  $pink: rgb(200, 0, 220);
  p {
    color: black;
    span {
      color: $pink;
    }
  }
</style>

Dynamic values without a runtime

We’ve seen that Svelte comes with most of the benefits of CSS-in-JS out-of-the-box — but without external dependencies! However, there’s one thing that third-party libraries can do that Svelte simply can’t: use JavaScript variables in CSS.

The following code is not valid and will not work:

<script>
  export let cols = 4;
</script>

<style>
  ul {
    display: grid;
    width: 100%;
    grid-column-gap: 16px;
    grid-row-gap: 16px;
    grid-template-columns: repeat({cols}, 1fr);
  }
</style>

<ul>
  <slot />
</ul>

We can, however, achieve similar functionality by using CSS variables.

<script>
  export let cols = 4;
</script>

<style>
  ul {
    display: grid;
    width: 100%;
    grid-column-gap: 16px;
    grid-row-gap: 16px;
    grid-template-columns: repeat(var(--columns), 1fr);
  }
</style>

<ul style="--columns:{cols}">
  <slot />
</ul>

I’ve written CSS in all kinds of different ways over the years: Sass, Shadow DOM, CSS-in-JS, BEM, atomic CSS and PostCSS. Svelte offers the most intuitive, approachable and user-friendly styling API. If you want to read more about this topic then check out the aptly titled The Zen of Just Writing CSS by Rich Harris.


What I Like About Writing Styles with Svelte originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/what-i-like-about-writing-styles-with-svelte/feed/ 9 297067
What is the difference between CSS variables and preprocessor variables? https://css-tricks.com/difference-between-types-of-css-variables/ https://css-tricks.com/difference-between-types-of-css-variables/#comments Tue, 25 Oct 2016 12:30:29 +0000 http://css-tricks.com/?p=246274 Variables are one of the major reasons CSS preprocessors exist at all. The ability to set a variable for something like a color, use that variable throughout the CSS you write, and know that it will be consistent, DRY, and …


What is the difference between CSS variables and preprocessor variables? originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Variables are one of the major reasons CSS preprocessors exist at all. The ability to set a variable for something like a color, use that variable throughout the CSS you write, and know that it will be consistent, DRY, and easy to change is useful. You can use native CSS variables (“CSS Custom Properties”) for the same reasons. But there are also some important differences that should be made clear.

A simple example of preprocessor variable usage is like this:

$brandColor: #F06D06;

.main-header {
  color: $brandColor;
}
.main-footer {
  background-color: $brandColor;
}

That was the SCSS variant of Sass, but all CSS preprocessors offer the concept of variables: Stylus, Less, PostCSS, etc.

The above code would do nothing in a browser. The browser wouldn’t understand the declarations and toss them out. Preprocessors need to compile into CSS to be used. This code would compile to:

.main-header {
  color: #F06D06;
}
.main-footer {
  background-color: #F06D06;
}

This is now valid CSS. The variable was part of the preprocessor language, not CSS itself. Once the code compiles, the variables are gone.

More recently, native CSS has started supporting CSS variables, or “CSS Custom Properties”. It allows you to work with variables directly in CSS. There is no compiling.

A simple example of CSS custom property usage is like this:

:root {
  --main-color: #F06D06;
}

.main-header {
  color: var(--main-color);
}
.main-footer {
  background-color: var(--main-color);
}

These two demos achieve the exact same thing. We were able to define a color once and use it twice.

So then… why use one over another?

Why would you use native CSS custom properties?

  • You can use them without the need of a preprocessor.
  • They cascade. You can set a variable inside any selector to set or override its current value.
  • When their values change (e.g. media query or other state), the browser repaints as needed.
  • You can access and manipulate them in JavaScript.

Regarding cascade, here’s a simple example of that:

:root {
  --color: red;
}
body {
  --color: orange;
}
h2 {
  color: var(--color);
}

Any <h2> will be orange, because any <h2> will be a child of <body>, which has a higher applicable specificity.

You could even re-set variables within media queries and have those new values cascade through everywhere using them, something that just isn’t possible with preprocessor variables.

Check out this example where a media query changes the variables which are used to set up a very simple grid:

Rob Dodson advocates for CSS Custom Properties in CSS Variables: Why Should You Care?

The variables that [preprocessors] use suffer from a major drawback, which is that they’re static and can’t be changed at runtime. Adding the ability to change variables at runtime not only opens the door to things like dynamic application theming, but also has major ramifications for responsive design and the potential to polyfill future CSS features.

He includes a demo where JavaScript changes styles. It doesn’t change the styles on elements directly, it’s just resetting some CSS variables on-the-fly:

Wes Bos has a demo of this in action as well:

See the Pen Update CSS Variables with JS by Wes Bos (@wesbos) on CodePen.

Note there is a bunch of stuff about CSS custom properties I’m leaving out here. You can set fallbacks. You can use calc() with them. There are a bunch of cool tricks you can do with them. See the homework section below!

Why use preprocessor variables?

  • The big one: There are no inherit browser support considerations. They compile down into normal CSS.
  • Little stuff: Like you can strip units from a value if you had to.

You could use them together

There are pretty compelling reasons to use both. You could absolutely have a CSS preprocessor output CSS custom properties. Ivan Ivanov created a demo that allows you to write using the syntax of CSS custom properties, and through Sass, output code that has fallbacks:

See the Pen Use CSS4 variables right now by $i.van(ov) (@vank0) on CodePen.

I tend to think that once we can use CSS custom properties without worrying about browser support, that we’d just use them to do all our variable handling. We might still use preprocessors for other conveniences, but the variable handling in native CSS seems so good it’s probably worth just going all-in on that.

Browser support of CSS Custom Properties

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
4931No1610

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
10810710810.0-10.2

Homework time: level up!

1) Watch Lea Verou’s CSS Variables: var(–subtitle);

She covers plenty of practical applications, as well as some trickery like taking control of when variables cascade and some gotchas.

2) Watch David Khourshid’s Reactive Animations with CSS

David shares the idea that connecting DOM events with CSS variables can do some really awesome UI stuff with not much code. Check out his slides (starting from #26) that show off how awesome this is.

3) Read Harry Roberts Pragmatic, Practical, and Progressive Theming with Custom Properties

His article explains how user theming of sites gets a heck of a lot easier with CSS variables.

4) Read Roman Komarov’s Conditions for CSS Variables

Despite it being talked about every so often, there are no logical gates in CSS (e.g. @if (true) { }). We fake it sometimes with things like :checked, but that’s dependent on the DOM. Roman shows off a trick where you can use 0 or 1 on a variable and then use that with calc() to simulate boolean logic.


What is the difference between CSS variables and preprocessor variables? originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/difference-between-types-of-css-variables/feed/ 17 246274