Implementing Private Variables In JavaScript

JavaScript (or ECMAScript) is the programming language that powers the web. Created in May 1995 by Brendan Eich, it’s found its place as a widely-used and versatile technology. Despite its success, it’s been met with its fair share of criticism, especially for idiosyncrasies. Things like objects being casted to string form when used as indices, 1 == "1" returning true, or the notoriously confusing this keyword. A particularly interesting quirk though, is the existence of various techniques for variable privacy.

In its current state, there is no “direct” way to create a private variable in JavaScript. In other languages, you can use the private keyword or double-underscores and everything works, but variable privacy in JavaScript carries characteristics that make it seem more akin to an emergent trait of the language rather than an intended functionality. Let’s introduce some background to our problem.

The “var” keyword

Before 2015, there was essentially one way to create a variable, and that was the var keyword. var is function-scoped, meaning that variables instantiated with the keyword would only be accessible to code within the function. When outside of a function, or “global” essentially, the variable will be accessible to anything executed after the definition of the variable. If you try to access the variable in the same scope before its definition, you will get undefined rather than an error. This is due to the way the var keyword “hoists.”

// Define "a" in global scope
var a = 123; // Define "b" in function scope
(function() { console.log(b); //=> Returns "undefined" instead of an error due to hoisting. var b = 456;
})(); console.log(a); // => 123
console.log(b); // Throws "ReferenceError" exception, because "b" cannot be accessed from outside the function scope.

The birth of ES6 variables

In 2015, ES6/ES2015 was made official, and with it came two new variable keywords: let and const. Both were block-scoped, meaning that variables created with the keywords would be accessible from anything within the same pair of braces. Same as with var, but the let and const variables could not be accessed outside of block scope with loops, functions, if statements, braces, etc.

const a = 123; // Block scope example #1
if (true) { const b = 345;
} // Block scope example #2
{ const c = 678;
} console.log(a); // 123
console.log(b); // Throws "ReferenceError" because "b" cannot be accessed from outside the block scope.
console.log(c); // Throws "ReferenceError" because "b" cannot be accessed from outside the block scope.

Since code outside of the scope cannot access the variables, we get an emergent trait of privacy. We’re going to cover some techniques for implementing it in different ways.

Using functions

Since functions in JavaScript also are blocks, all variable keywords work with them. In addition, we can implement a very useful design pattern called the “module.”

The Module Design Pattern

Google relies on the Oxford Dictionary to define a “module”:

Any of a number of distinct but interrelated units from which a program may be built up or into which a complex activity may be analyzed.

—”Module” Definition 1.2

The module design pattern is very useful in JavaScript because it combines public and private components and it allows us to break a program into smaller components, only exposing what another part of the program should be able to access through a process called “encapsulation.” Through this method, we expose only what needs to be used and can hide the rest of the implementation that doesn’t need to be seen. We can take advantage of function scope to implement this.

const CarModule = () => { let milesDriven = 0; let speed = 0; const accelerate = (amount) => { speed += amount; milesDriven += speed; } const getMilesDriven = () => milesDriven; // Using the "return" keyword, you can control what gets // exposed and what gets hidden. In this case, we expose // only the accelerate() and getMilesDriven() function. return { accelerate, getMilesDriven }
}; const testCarModule = CarModule();

With this, we can get the number of miles driven, as well as the amount of acceleration, but since the user doesn’t need access to the speed in this case, we can hide it by only exposing the accelerate() and getMilesDriven() method. Essentially, speed is a private variable, as it is only accessible to code inside of the same block scope. The benefit to private variables begins to become clear in this situation. When you remove the ability to access a variable, function, or any other internal component, you reduce the surface area for errors resulting from someone else mistakenly using something that wasn’t meant to be.

The alternative way

In this second example, you’ll notice the addition of the this keyword. There’s a difference between the ES6 arrow function ( => ) and the traditional function(){}. With the function keyword, you can use this, which will be bound to the function itself, whereas arrow functions don’t allow any kind of use of the this keyword. Both are equally-valid ways to create the module. The core idea is to expose parts that should be accessed and leave other parts that should not be interacted with, hence both public and private data.

function CarModule() { let milesDriven = 0; let speed = 0; // In this case, we instead use the "this" keyword, // which refers to CarModule this.accelerate = (amount) => { speed += amount; milesDriven += speed; } this.getMilesDriven = () => milesDriven;
} const testCarModule = new CarModule();

Enter ES6 Classes

Classes were another addition that came with ES6. Classes are essentially syntactic sugar — in other words, still a function, but potentially “sweetening” it into a form that’s easier to express. With classes, variable privacy is (as of now) close to impossible without making some major changes to the code.

Let’s take a look at an example class.

class CarModule { /* milesDriven = 0; speed = 0; */ constructor() { this.milesDriven = 0; this.speed = 0; } accelerate(amount) { this.speed += amount; this.milesDriven += this.speed; } getMilesDriven() { return this.milesDriven; }
} const testCarModule = new CarModule();

One of the first things that stands out is that the milesDriven and speed variable are inside of a constructor() function. Note that you can also define the variables outside of the constructor (as shown in the code comment), but they are functionally the same regardless. The problem is that these variables will be public and accessible to elements outside of the class.

Let’s look at some ways to work around that.

Using an underscore

In cases where privacy is to prevent collaborators from making some catastrophic mistake, prefixing variables with an underscore (_), despite still being “visible” to the outside, can be sufficient to signal to a developer, “Don’t touch this variable.” So, for example, we now have the following:

// This is the new constructor for the class. Note that it could
// also be expressed as the following outside of constructor().
/* _milesDriven = 0; _speed = 0;
constructor() { this._milesDriven = 0; this._speed = 0;

While this does work for its specific use case, it’s still safe to say that it’s less than ideal on many levels. You can still access the variable but you also have to modify the variable name on top of that.

Putting everything inside the constructor

Technically, there is a method for variable privacy in a class that you can use right now, and that’s placing all variables and methods inside the constructor() function. Let’s take a look.

class CarModule { constructor() { let milesDriven = 0; let speed = 0; this.accelerate = (amount) => { speed += amount; milesDriven += speed; } this.getMilesDriven = () => milesDriven; }
} const testCarModule = new CarModule();
console.log(testCarModule.speed); // undefined -- We have true variable privacy now.

This method accomplishes true variable privacy in the sense that there is no way to directly access any variables that aren’t intentionally exposed. The problem is that we now have, well, code that doesn’t look all that great compared to what we had before, in addition to the fact that it defeats the benefits of the syntactic sugar we had with classes. At this point, we might as well be using the function() method.

Using WeakMap

There’s another, more creative way to go about making a private variable, and that’s using WeakMap(). Although it may sound similar to Map, the two are very different. While maps can take any type of value as a key, a WeakMap only take objects and deletes the values in the WeakMap when the object key is garbage collected. In addition, a WeakMap cannot be iterated through, meaning that you must have access to the reference to an object key in order to access a value. This makes it rather useful for creating private variables, since the variables are effectively invisible.

class CarModule { constructor() { = new WeakMap();, { milesDriven: 0, speed: 0 }); } accelerate(amount) { // In this version, we instead create a WeakMap and // use the "this" keyword as a key, which is not likely // to be used accidentally as a key to the WeakMap. const data =; const speed = data.speed + amount; const milesDriven = data.milesDriven + data.speed;{ speed, milesDriven }); } this.getMilesDriven = () =>;
} const testCarModule = new CarModule();
console.log(; //=> WeakMap { [items unknown] } -- This data cannot be accessed easily from the outside!

This solution is good at preventing an accidental usage of the data, but it isn’t truly private, since it can still be accessed from outside the scope by substituting this with CarModule. In addition, it adds a fair amount of complexity to the mix and, therefore, isn’t the most elegant solution.

Using symbols to prevent collisions

If the intent is to prevent name collisions, there is a useful solution using Symbol. These are essentially instances that can behave as unique values that will never be equal to anything else, except its own unique instance. Here’s an example of it in action:

class CarModule { constructor() { this.speedKey = Symbol("speedKey"); this.milesDrivenKey = Symbol("milesDrivenKey"); this[this.speedKey] = 0; this[this.milesDrivenKey] = 0; } accelerate(amount) { // It's virtually impossible for this data to be // accidentally accessed. By no means is it private, // but it's well out of the way of anyone who would // be implementing this module. this[this.speedKey] += amount; this[this.milesDrivenKey] += this[this.speedKey]; } getMilesDriven() { return this[this.milesDrivenKey]; }
} const testCarModule = new CarModule();
console.log(testCarModule.speed); // => undefined -- we would need to access the internal keys to access the variable. Like the underscore solution, this method more or less relies on naming conventions to prevent confusion.

TC39 private class field proposal

Recently, a new proposal was introduced that would introduce private variables to classes. It’s rather simple: put a # before the name of a variable, and it becomes private. No extra structural changes needed.

class CarModule { #speed = 0 #milesDriven = 0 accelerate(amount) { // It's virtually impossible for this data to be // accidentally accessed. By no means is it private, // but it's well out of the way of anyone who would // be implementing this module. this.#speed += amount; this.#milesDriven += speed; } getMilesDriven() { return this.#milesDriven; }
} const testCarModule = new CarModule();
console.log(testCarModule.speed); //=> undefined -- we would need to access the internal keys to access the variable.

The private class field proposal is not standard and cannot be done without using Babel as of this writing, so you’ll have to wait a bit for it to be usable on major browsers, Node, etc.


That sums up the various ways you can implement private variables in JavaScript. There isn’t a single “correct” way to do it. These will work for different needs, existing codebases, and other constraints. While each has advantages and disadvantages, ultimately, all methods are equally valid as long as they effectively solve your problem.

Thanks for reading! I hope this provides some insight into how scope and variable privacy can be applied to improve your JavaScript code. This is a powerful technique and can support so many different methods and make your code more usable and bug-free. Try out some new examples for yourself and get a better feel.

The post Implementing Private Variables In JavaScript appeared first on CSS-Tricks.

Weekly Platform News: Favicon Guidelines, Accessibility Testing, Web Almanac

Šime posts regular content for web developers on

Google posts guidelines for defining favicons

Jamie Leach: Google Search now displays favicons in search results on mobile. Your favicon should be a multiple of 48×48 (Google will re-scale it to 16×16 for use in search results). If a website doesn’t have a favicon or Google deems the favicon inappropriate, a generic globe icon will be displayed instead.

Your favicon should be a visual representation of your website’s brand, in order to help users quickly identify your site when they scan through search results.

Top websites are surprisingly inconsistent in the way they declare icons (via <link> elements in the page’s head). Twitter and Pinterest, two relatively modern progressive web apps, provide icons in two sizes.

<!-- example -->
<link rel="icon" href="/icon-32x32.png">
<link rel="apple-touch-icon" href="/icon-192x192.png">

The Paciello Group releases ARC Toolkit

The Paciello Group: ARC Toolkit, our professional-level accessibility testing tool, is now available as a Chrome DevTools extension. This tool detects issues related to the WCAG 2.1 guidelines. You can run the test on the entire page or just the node selected in the DevTools Elements panel.

Remember, automated accessibility tools are only able to find some accessibility issues, and manual testing is necessary to ensure full accessibility. Lighthouse (via the Audits panel) suggests manual checks after performing an accessibility audit.

Other news

  • Jeff Jaffe: W3C and WHATWG have reached an agreement to collaborate on the development of HTML. “W3C shall encourage the community … to contribute directly to the WHATWG HTML and DOM repositories; raising issues, proposing solutions, commenting on proposed solutions, and indicating support or otherwise for proposals.”
  • Paul Calvano: “There is a significant gap in the first- vs. third-party resource age of CSS and web fonts. 95% of first-party fonts are older than one week compared to 50% of third-party fonts … This makes a strong case for self-hosting web fonts!”
  • Rachel Andrew: The CSS subgrid value is a relatively straightforward addition to grid layout. For example, if you have nested grids, and you apply grid-template-rows: subgrid to the child grid, then this grid will use the row tracks of the parent grid instead of creating its own row tracks. That’s all there is to it. (This feature is currently only supported in Firefox Nightly.)
  • GitHub Blog: GitHub can now generate automated security fixes for your dependencies with known security vulnerabilities. On GitHub’s website, check your repository’s Security tab for security alerts. If you open an alert and press the “Create automated security fix” button, GitHub will create an automated pull request that fixes the security vulnerability.
  • Rick Viscomi: HTTP Archive plans to release the first annual Web Almanac in November, a report of the state of the web with interesting insights written by different experts. About 50 volunteers from the web community are currently working on it, and they are looking for more contributors.

The post Weekly Platform News: Favicon Guidelines, Accessibility Testing, Web Almanac appeared first on CSS-Tricks.

Reducing motion with the picture element

Here’s a bonafide CSS/HTML trick from Brad Frost and Dave Rupert where they use the <picture> element to switch out a GIF file with an image if the user has reduced motion enabled. This is how Brad goes about implementing that:

<picture> <!-- This image will be loaded if the media query is true --> <source srcset="no-motion.jpg" media="(prefers-reduced-motion: reduce)"></source> <!-- Otherwise, load this gif --> <img srcset="animated.gif" alt="brick wall"/>

How nifty is this? It makes me wonder if there are other ways this image-switching technique can be used besides accessibility and responsive images…

Also, it’s worth noting that Eric Bailey wrote about the reduced motion media query a while back where he digs into its history and various approaches to use it.

Direct Link to ArticlePermalink

The post Reducing motion with the picture element appeared first on CSS-Tricks.

Inspiring Wallpapers For A Colorful June (2019 Edition)

Inspiring Wallpapers For A Colorful June (2019 Edition)

Inspiring Wallpapers For A Colorful June (2019 Edition)

Cosima Mielke

No matter if June means the beginning of summer for you, that monsoon season is here, or that winter is just around the corner, our new wallpapers are bound to sweeten the beginning of the month with some fresh inspiration.

Created by artists and designers from across the globe, the designs featured in this collection are part of our wallpaper series which has been going on for more than nine years already. Every month, we challenge you, the community, to submit your wallpaper designs to it. It’s an opportunity to let your creative ideas run free and use your favorite tools — without the pressure of meeting project requirements or satisfying stakeholders. It’s only you and your creative process. And, well, we are very thankful to everyone who has taken on this challenge and is still continuing to do so to cater for diverse and unique results each time anew.

To accompany you through the new month — and beyond — the wallpapers all come in versions with and without a calendar for June 2019 and can be downloaded for free. For some extra variety, you’ll also find a selection of favorites from past years’ editions at the end of this post. Enjoy!

Please note that:

  • All images can be clicked on and lead to the preview of the wallpaper,
  • You can feature your work in our magazine, too. So if you have an idea for a July wallpaper design, please don’t hesitate to submit it. We’d love to see what you’ll come up with.

Further Reading on SmashingMag:

Summer Is Coming

“Imagine a sunny beach and an endless blue sea. Imagine yourself right there. Is it somewhere in Greece? The Mediterranean? North Africa? Now turn around and start wandering through those picturesque, narrow streets. See all those authentic white houses with blue doors and blue windows? Feel the fragrance of fresh flowers? Stop for a second. Take a deep breath. Seize the moment. Breathe in. Breathe out. Now slowly open your eyes. Not quite there yet? Don’t worry. You will be soon! Summer is coming…” — Designed by PopArt Studio from Serbia.

Summer Is Coming

Melting Away

Designed by Ricardo Gimenes from Sweden.

Melting Away

It’s Bauhaus Year

“This year is Bauhaus year – therefore I created a screenprint of one of the most famous buildings from the Bauhaus architect Mies van der Rohe for you. So, enjoy the Barcelona Pavillon for your June wallpaper.” — Designed by Anne Korfmacher from Germany.

It’s Bauhaus Year

Sunset With Crabs

“In the sunset the crabs come to the surface. That little boat can’t sail, but after seeing the crabs it gets power and finally… it sails!” — Designed by Veronica Valenzuela from Spain.

Sunset With Crabs

Monsoon Season

“Rain is the art of nature, and umbrella the art of man. Walking with your umbrella on a rainy day, you connect these arts!” — Designed by Themehigh from Calicut.

Monsoon Season

Take Your First Step In Spirituality

“Yoga is a way of finding your true self. This International Yoga Day, take a path of a spiritual journey and see where it leads you in your life.” — Designed by Kiran Shirke from India.

Take Your First Step In Spirituality

Oldies But Goodies

So many beautiful, unique, and inspiring wallpapers have come to life as a part of our monthly challenge in the past nine years. Here are some June favorites from past editions. Please note that these wallpapers don’t come with a calendar.

Deep Dive

“Summer rains, sunny days and a whole month to enjoy. Dive deep inside your passions and let them guide you.” — Designed by Ana Masnikosa from Belgrade, Serbia.

Deep Dive

Pineapple Summer Pop

“I love creating fun and feminine illustrations and designs. I was inspired by juicy tropical pineapples to celebrate the start of summer.” — Designed by Brooke Glaser from Honolulu, Hawaii.

Pineapple Summer Pop

Travel Time

“June is our favorite time of the year because the keenly anticipated sunny weather inspires us to travel. Stuck at the airport, waiting for our flight but still excited about wayfaring, we often start dreaming about the new places we are going to visit. Where will you travel to this summer? Wherever you go, we wish you a pleasant journey!” — Designed by PopArt Studio from Serbia.

Travel Time

Summer Surf

“Summer vibes…” — Designed by Antun Hirsman from Croatia.

Summer Surf

Shine Your Light

“Shine your light, Before the fight, Just like the sun, Cause we don’t have to run.” — Designed by Anh Nguyet Tran from Vietnam.

Shine Your Light

Tropical Vibes

“With summer just around the corner, I’m already feeling the tropical vibes.” — Designed by Melissa Bogemans from Belgium.

Tropical Vibes

Window Of Opportunity

“‘Look deep into nature and then you will understand everything better,’ A.E.” — Designed by Antun Hiršman from Croatia.

Window Of Opportunity

Start Your Day

Designed by Elise Vanoorbeek from Belgium.

Start Your Day

Doughnuts Galore

“Friday, June 6th is National Doughnut Day. Designer Dorothy Timmer found inspiration in the sweet treats and brought the obscure holiday into the spotlight. Doughnuts are delicious. That is all.” — Designed by Clarity Creative Group from Orlando, FL.

Doughnuts Galore

Nine Lives!

“I grew up with cats around (and drawing them all the time). They are so funny… one moment they are being funny, the next they are reserved. If you have place in your life for a pet, adopt one today!” — Designed by Karen Frolo from the United States.

Nine Lives!

Getting Better Everyday

“The eternal forward motion to get better and excel.” — Designed by Zachary Johnson-Medland from the United States.

Getting Better Everyday

Expand Your Horizons

“It’s summer! Go out, explore, expand your horizons!” — Designed by Dorvan Davoudi from Canada.

Expand Your Horizons

Handmade Pony Gone Wild

“This piece was inspired by the My Little Pony cartoon series. Because those ponies irritated me so much as a kid, I always wanted to create a bad ass pony.” — Designed by Zaheed Manuel from South Africa.

Hand made pony gone wild

The Kids Looking Outside

“These are my cats looking out of the window. Because it is Children’s Day in June in a lot of countries I chose to make a wallpaper with this photo of my cats. The cats are like kids, they always want to play and love to be outside! Also, most kids love cats!” — Designed by Kevin van Geloven from The Netherlands.

The Kids Looking Outside

Good Design Is A Tough Knitted Job

“I came across this awesome tutorial on Tuts+, about creating a card with knitted effect, so I took it up a notch and said, hey, why can’t I make a couple wallpapers using what I’ve learnt… So here we are.” — Designed by Brian Jangima from Kenya.

Good Design is a Tough Knitted Job

Viking Meat War

Designed by Ricardo Gimenes from Sweden.

Viking Meat War

Sunset In Jamaica

“Photo from a recent trip to Jamaica edited to give a retro look and feel.” — Designed by Tommy Digiovanni from the USA.

Sunset In Jamaica — Preview

Gipsy Spirit

“Soft spring colors and boho feathers.” — Designed by Denise Johnson from Chicago.

Gipsy Spirit
  • preview
  • without calendar: 1024×768, 1280×800, 1280×1024, 1440×900, 1600×1200, 1920×1200
  • Hello Winter!

    Designed by Tazi Design from Australia.

    Hello Winter!

    Join In Next Month!

    Please note that we respect and carefully consider the ideas and motivation behind each and every artist’s work. This is why we give all artists the full freedom to explore their creativity and express emotions and experience throughout their works. This is also why the themes of the wallpapers weren’t anyhow influenced by us but rather designed from scratch by the artists themselves.

    Thank you to all designers for their participation. Join in next month!

    Top 10 Color Pickers for 2019

    Saving color palettes you find online or as you’re working on a design is not always an easy process. You could use the browser’s Inspect tool to grab the hex code or grab a screenshot and use Photoshop later on to pull the colors from it.

    Or you could simplify the process and grab a dedicated color picker tool that will allow you to grab color from any website, on desktop or on mobile without having to leave your browser window. Here are 10 best color pickers that will make it easy to save color palettes.

    1. Instant Eyedropper

    Instant Eyedropper is a free Windows-only tool that makes it easy to grab a color from anywhere on your screen. Once you install this lightweight app, it will sit in your system tray. All you have to do is click its icon and choose a color, then the app will copy the code to your clipboard. The app supports the following color code formats: HTML, HEX, Delphi Hex, Visual Basic Hex, RGB, HSB, and Long.

    2. ColorPic

    ColorPic is another lightweight Windows color picker tool that works with all major versions of Windows. It’s not a free program although it offers a free trial. It was designed to work specifically with high resolution screens and supports HEX, RGB, and CMYK color formats. You can save up to 16 colors in the palettes, and use 4 advanced color mixers to adjust the colors.

    3. Eye Dropper

    Eye Dropper is a browser extension that works on Google Chrome and any other Chromium-based browser. The extension allows you to quickly and easily grab a color from anywhere in your browser and displays it in HEX or RGB format. You can save colors to history and they are automatically copied to your clipboard when you pick a color. The extension is free to use.

    4. ColorPick Eyedropper

    ColorPick Eyedropper is the second-most popular browser extension that works in Chrome and Chromium-based browsers. What sets it apart from the Eye Dropper extension above is the ability to zoom in on any area of the browser window to help you focus in on the exact color you want. The app is free for personal use and it also has its own desktop app if you want a tool that works outside your browser window.

    5. ColorZilla

    ColorZilla is a Firefox extension that allows you to grab any color from any page that’s open in your Firefox browser window. This extension has a built-in palette that allows you to quickly choose a color and save the most used colors in a custom palette. You can also easily create CSS gradients. The extension is free and supports HEX and RGB color formats. It can also be used with a Chrome browser.

    6. Rainbow Color Tools

    Rainbow Color Tools is another free Firefox extension that makes color picking easy. The extension lets you easily pick a color and it also includes a website analyzer that extracts the color scheme from the current website’s images and CSS. It supports RGB and HSV color formats and allows you to save the colors into your own personal library that lets you tag images based on websites you picked colors from or your own tags.

    7. ColorSnapper 2

    The ColorSnapper 2 is a color picker for Mac users that helps them find a color anywhere on their screen. The app is invoked by clicking the menu icon or through a global shortcut and it has a unique high-precision mode for better accuracy. You can choose between 10 different color formats and control the app with gestures and keyboard shortcuts. The app is available in the app store and comes with a 14-day free trial.

    8. Just Color Picker

    Just Color Picker is a multi-platform utility for choosing colors. This tool allows you to pick colors, save them, edit them, and combine them into color palettes ready for use in other applications. It supports a wide range of color formats and includes a zoom tool for better accuracy, the ability to edit Photoshop and Gimp color swatches, and it can even calculate distance between two pixels.

    9. iDropper

    iDropper is a color picker for iOS devices. It’s compatible with iPhones and iPads so if you do design work on your iPad, you’ll easily be able to grab colors, save them, and use them in any application. You can save colors to your favorites and supports RGB, HEX, HSV, and CMYK format. The app is free to download and use.

    10. Pixolor

    If you belong to team Android, then be sure to check out the Pixolor app. When you enable the app, it shows a floating circle over other apps along with the color information beneath it. To copy the color code, all you have to do is click the Share button or tap outside the circle overlay. The app supports RGB and HEX color formats.


    Featured image via DepositPhotos.

    Add Realistic Chalk and Sketch Lettering Effects with Sketch’it – only $5!

    p img {display:inline-block; margin-right:10px;}
    .alignleft {float:left;}
    p.showcase {clear:both;}
    body#browserfriendly p, body#podcast p, div#emailbody p{margin:0;}

    A Practical Use Case for Vue Render Functions: Building a Design System Typography Grid

    This post covers how I built a typography grid for a design system using Vue render functions. Here’s the demo and the code. I used render functions because they allow you to create HTML with a greater level of control than regular Vue templates, yet surprisingly I couldn’t find very much when I web searched around for real-life, non-tutorial applications of them. I’m hoping this post will fill that void and provide a helpful and practical use case on using Vue render functions.

    I’ve always found render functions to be a little out-of-character for Vue. While the rest of the framework emphasizes simplicity and separation of concerns, render functions are a strange and often difficult-to-read mix of HTML and JavaScript.

    For example, to display:

    Some cool text

    …you need:

    render(createElement) { return createElement("div", { class: "container" }, [ createElement("p", { class: "my-awesome-class" }, "Some cool text") ])

    I suspect that this syntax turns some people off, since ease-of-use is a key reason to reach for Vue in the first place. This is a shame because render functions and functional components are capable of some pretty cool, powerful stuff. In the spirit of demonstrating their value, here’s how they solved an actual business problem for me.

    Quick disclaimer: It will be super helpful to have the demo open in another tab to reference throughout this post.

    Defining criteria for a design system

    My team wanted to include a page in our VuePress-powered design system showcasing different typography options. This is part of a mockup that I got from our designer.

    A screenshot of the typographic design system. There are four columns where the first shows the style name with the rendered style, second is the element or class, third shows the properties that make the styles, and fourth is the defined usage.

    And here’s a sample of some of the corresponding CSS:

    h1, h2, h3, h4, h5, h6 { font-family: "balboa", sans-serif; font-weight: 300; margin: 0;
    } h4 { font-size: calc(1rem - 2px);
    } .body-text { font-family: "proxima-nova", sans-serif;
    } .body-text--lg { font-size: calc(1rem + 4px);
    } .body-text--md { font-size: 1rem;
    } .body-text--bold { font-weight: 700;
    } .body-text--semibold { font-weight: 600;

    Headings are targeted with tag names. Other items use class names, and there are separate classes for weight and size.

    Before writing any code, I created some ground rules:

    • Since this is really a data visualization, the data should be stored in a separate file.
    • Headings should use semantic heading tags (e.g. <h1>, <h2>, etc.) instead of having to rely on a class.
    • Body content should use paragraph (<p>) tags with the class name (e.g. <p class="body-text--lg">).
    • Content types that have variations should be grouped together by wrapping them in the root paragraph tag, or corresponding root element, without a styling class. Children should be wrapped with <span> and the class name.
    <p> <span class="body-text--lg">Thing 1</span> <span class="body-text--lg">Thing 2</span>
    • Any content that’s not demonstrating special styling should use a paragraph tag with the correct class name and <span> for any child nodes.
    <p class="body-text--semibold"> <span>Thing 1</span> <span>Thing 2</span>
    • Class names should only need to be written once for each cell that’s demonstrating styling.

    Why render functions make sense

    I considered a few options before starting:


    I like hardcoding when appropriate, but writing my HTML by hand would have meant typing out different combinations of the markup, which seemed unpleasant and repetitive. It also meant that data couldn’t be kept in a separate file, so I ruled out this approach.

    Here’s what I mean:

    Heading 1


    Balboa Light, 30px

    Product title (once on a page) Illustration headline

    Using a traditional Vue template

    This would normally be the go-to option. However, consider the following:

    See the Pen
    Different Styles Example
    by Salomone Baquis (@soluhmin)
    on CodePen.

    In the first column, we have:

    – An <h1>> tag rendered as-is.
    – A <p> tag that groups some <span> children with text, each with a class (but no special class on the <p> tag).
    – A <p> tag with a class and no children.

    The result would have meant many instances of v-if and v-if-else, which I knew would get confusing fast. I also disliked all of that conditional logic inside the markup.

    Because of these reasons, I chose render functions. Render functions use JavaScript to conditionally create child nodes based on all of the criteria that’s been defined, which seemed perfect for this situation.

    Data model

    As I mentioned earlier, I’d like to keep typography data in a separate JSON file so I can easily make changes later without touching markup. Here’s the raw data.

    Each object in the file represents a different row.

    { "text": "Heading 1", "element": "h1", // Root wrapping element. "properties": "Balboa Light, 30px", // Third column text. "usage": ["Product title (once on a page)", "Illustration headline"] // Fourth column text. Each item is a child node. }

    The object above renders the following HTML:

    Heading 1


    Balboa Light, 30px

    Product title (once on a page) Illustration headline

    Let’s look at a more involved example. Arrays represent groups of children. A classes object can store classes. The base property contains classes that are common to every node in the cell grouping. Each class in variants is applied to a different item in the grouping.

    { "text": "Body Text - Large", "element": "p", "classes": { "base": "body-text body-text--lg", // Applied to every child node "variants": ["body-text--bold", "body-text--regular"] // Looped through, one class applied to each example. Each item in the array is its own node. }, "properties": "Proxima Nova Bold and Regular, 20px", "usage": ["Large button title", "Form label", "Large modal text"]

    Here’s how that renders:

    Body Text - Large Body Text - Large

    body-text body-text--lg body-text--bold body-text body-text--lg body-text--regular

    Proxima Nova Bold and Regular, 20px

    Large button title Form label Large modal text

    The basic setup

    We have a parent component, TypographyTable.vue, which contains the markup for the wrapper table element, and a child component, TypographyRow.vue, which creates a row and contains our render function.

    I loop through the row component, passing the row data as props.

    <template> <section> <!-- Headers hardcoded for simplicity --> 





    <!-- Loop and pass our data as props to each row --> <typography-row v-for="(rowData, index) in $options.typographyData" :key="index" :row-data="rowData" /> </section> </template> import TypographyData from "@/data/typography.json"; import TypographyRow from "./TypographyRow"; export default { // Our data is static so we don't need to make it reactive typographyData: TypographyData, name: "TypographyTable", components: { TypographyRow } };

    One neat thing to point out: the typography data can be a property on the Vue instance and be accessed using $options.typographyData since it doesn’t change and doesn’t need to be reactive. (Hat tip to Anton Kosykh.)

    Making a functional component

    The TypographyRow component that passes data is a functional component. Functional components are stateless and instanceless, which means that they have no this and don’t have access to any Vue lifecycle methods.

    The empty starting component looks like this:

    // No <template>
    export default { name: "TypographyRow", functional: true, // This property makes the component functional props: { rowData: { // A prop with row data type: Object } }, render(createElement, { props }) { // Markup gets rendered here }

    The render method takes a context argument, which has a props property that’s de-structured and used as the second argument.

    The first argument is createElement, which is a function that tells Vue what nodes to create. For brevity and convention, I’ll be abbreviating createElement as h. You can read about why I do that in Sarah’s post.

    h takes three arguments:

    1. An HTML tag (e.g. div)
    2. A data object with template attributes (e.g. { class: 'something'})
    3. Text strings (if we’re just adding text) or child nodes built using h
    render(h, { props }) { return h("div", { class: "example-class }, "Here's my example text")

    OK, so to recap where we are at this point, we’ve covered creating:

    • a file with the data that’s going to be used in my visualization;
    • a regular Vue component where I’m importing the full data file; and
    • the beginning of a functional component that will display each row.

    To create each row, the data from the JSON file needs to be passed into arguments for h. This could be done all at once, but that involves a lot of conditional logic and is confusing.

    Instead, I decided to do it in two parts:

    1. Transform the data into a predictable format.
    2. Render the transformed data.

    Transforming the common data

    I wanted my data in a format that would match the arguments for h, but before doing this, I wrote out how I wanted things structured:

    // One cell
    { tag: "", // HTML tag of current level cellClass: "", // Class of current level, null if no class exists for that level text: "", // Text to be displayed children: [] // Children each follow this data model, empty array if no child nodes

    Each object represents one cell, with four cells making up each row (an array).

    // One row
    [ { cell1 }, { cell2 }, { cell3 }, { cell4 } ]

    The entry point would be a function like:

    function createRow(data) { // Pass in the full row data and construct each cell let { text, element, classes = null, properties, usage } = data; let row = []; row[0] = createCellData(data) // Transform our data using some shared function row[1] = createCellData(data) row[2] = createCellData(data) row[3] = createCellData(data) return row;

    Let’s take another look at our mockup.

    The first column has styling variations, but the rest seem to follow the same pattern, so let’s start with those.

    Again, the desired model for each cell is:

    { tag: "", cellClass: "", text: "", children: []

    This gives us a tree-like structure for each cell since some cells have groups of children. Let’s use two functions to create the cells.

    • createNode takes each of our desired properties as arguments.
    • createCell wraps around createNode so that we can check if the text that we’re passing in is an array. If it is, we build up an array of child nodes.
    // Model for each cell
    function createCellData(tag, text) { let children; // Base classes that get applied to every root cell tag const nodeClass = "body-text body-text--md body-text--semibold"; // If the text that we're passing in as an array, create child elements that are wrapped in spans. if (Array.isArray(text)) { children = => createNode("span", null, child, children)); } return createNode(tag, nodeClass, text, children);
    // Model for each node
    function createNode(tag, nodeClass, text, children = []) { return { tag: tag, cellClass: nodeClass, text: children.length ? null : text, children: children };

    Now, we can do something like:

    function createRow(data) { let { text, element, classes = null, properties, usage } = data; let row = []; row[0] = "" row[1] = createCellData("p", ?????) // Need to pass in class names as text row[2] = createCellData("p", properties) // Third column row[3] = createCellData("p", usage) // Fourth column return row;

    We pass properties and usage to the third and fourth columns as text arguments. However, the second column is a little different; there, we’re displaying the class names, which are stored in the data file like:

    "classes": { "base": "body-text body-text--lg", "variants": ["body-text--bold", "body-text--regular"]

    Additionally, remember that headings don’t have classes, so we want to show the heading tag names for those rows (e.g. h1, h2, etc.).

    Let’s create some helper functions to parse this data into a format that we can use for our text argument.

    // Pass in the base tag and class names as arguments
    function displayClasses(element, classes) { // If there are no classes, return the base tag (appropriate for headings) return getClasses(classes) ? getClasses(classes) : element;
    } // Return the node class as a string (if there's one class), an array (if there are multiple classes), or null (if there are none.) // Ex. "body-text body-text--sm" or ["body-text body-text--sm body-text--bold", "body-text body-text--sm body-text--italic"]
    function getClasses(classes) { if (classes) { const { base, variants = null } = classes; if (variants) { // Concatenate each variant with the base classes return => base.concat(`${variant}`)); } return base; } return classes;

    Now we can do this:

    function createRow(data) { let { text, element, classes = null, properties, usage } = data; let row = []; row[0] = "" row[1] = createCellData("p", displayClasses(element, classes)) // Second column row[2] = createCellData("p", properties) // Third column row[3] = createCellData("p", usage) // Fourth column return row;

    Transforming the demo data

    This leaves the first column that demonstrates the styles. This column is different because we’re applying new tags and classes to each cell instead of using the class combination used by the rest of the columns:

    <p class="body-text body-text--md body-text--semibold">

    Rather than try to do this in createCellData or createNodeData, let’s make another function to sit on top of these base transformation functions and handle some of the new logic.

    function createDemoCellData(data) { let children; const classes = getClasses(data.classes); // In cases where we're showing off multiple classes, we need to create children and apply each class to each child. if (Array.isArray(classes)) { children = => // We can use "data.text" since each node in a cell grouping has the same text createNode("span", child, data.text, children) ); } // Handle cases where we only have one class if (typeof classes === "string") { return createNode("p", classes, data.text, children); } // Handle cases where we have no classes (ie. headings) return createNode(data.element, null, data.text, children);

    Now we have the row data in a normalized format that we can pass to our render function:

    function createRow(data) { let { text, element, classes = null, properties, usage } = data let row = [] row[0] = createDemoCellData(data) row[1] = createCellData("p", displayClasses(element, classes)) row[2] = createCellData("p", properties) row[3] = createCellData("p", usage) return row

    Rendering the data

    Here’s how we actually render the data to display:

    // Access our data in the "props" object
    const rowData = props.rowData; // Pass it into our entry transformation function
    const row = createRow(rowData); // Create a root "div" node and handle each cell
    return h("div", { class: "row" }, => renderCells(cell))); // Traverse cell values
    function renderCells(data) { // Handle cells with multiple child nodes if (data.children.length) { return renderCell( data.tag, // Use the base cell tag { // Attributes in here class: { group: true, // Add a class of "group" since there are multiple nodes [data.cellClass]: data.cellClass // If the cell class isn't null, apply it to the node } }, // The node content => { return renderCell( child.tag, { class: child.cellClass }, child.text ); }) ); } // If there are no children, render the base cell return renderCell(data.tag, { class: data.cellClass }, data.text);
    } // A wrapper function around "h" to improve readability
    function renderCell(tag, classArgs, text) { return h(tag, classArgs, text);

    And we get our final product! Here’s the source code again.

    Wrapping up

    It’s worth pointing out that this approach represents an experimental way of addressing a relatively trivial problem. I’m sure many people will argue that this solution is needlessly complicated and over-engineered. I’d probably agree.

    Despite the up-front cost, however, the data is now fully separated from the presentation. Now, if my design team adds or removes rows, I don’t have to dig into messy HTML — I just update a couple of properties in the JSON file.

    Is it worth it? Like everything else in programming, I guess it depends. I will say that this comic strip was in the back of my mind as I worked on this:

    A three-panel comic strip. First panel is a stick figure at a dinner table asking to pass the salt. Second panel is the same figure with no dialogue. Third panel is another figure saying he's building a system to pass the condiments and that it will save time in the long run. First figure says it's already been 20 minutes.

    Maybe that’s an answer. I’d love to hear all of your (constructive) thoughts and suggestions, or if you’ve tried other ways of going about a similar task.

    The post A Practical Use Case for Vue Render Functions: Building a Design System Typography Grid appeared first on CSS-Tricks.

    Creating Your Own React Validation Library: The Developer Experience (Part 3)

    Creating Your Own React Validation Library: The Developer Experience (Part 3)

    Creating Your Own React Validation Library: The Developer Experience (Part 3)

    Kristofer Selbekk

    If you’ve been following along this little article series, you’ve now learned how to put together your very own validation library. It can handle almost any challenge you can throw at it, and it even helps out with accessibility concerns! Its only downfall is that it sucks to work with.

    Yep, that’s right. The user experience from a developer point of view is seriously lacking. We don’t get any helpful warnings when we misspell words, misuse APIs or, well, anything, really!

    This article will guide you through how you can improve the developer experience of your validation library — or any library for that sake.

    Starting Out

    Since the last part of this article, we’ve pulled out all library code into its own files. Take a look at the CodeSandbox demo to see what we’re starting out with.

    Convenience Functions

    We want our library to be as simple as possible to use for the most common cases. A way to move towards that goal is to add convenient utility functions for certain functionality.

    One such feature could be to check if our form is valid — that is, if all error messages are null. This is something you typically check in your onSubmit handler, but it could be useful in your render-method too. Let’s implement it!

    const isFormValid = useMemo( () => Object.values(errors).every(error => error === null), [errors]

    We’ll provide this flag in our onSubmit form handler, as well as in our render method.

    There are plenty more of these that could be written, but I’ll let that be an exercise for the reader.

    Development Warnings And Invariants

    One of React’s greatest features is its many helpful console warnings while developing. We should provide the same sort of quality to our users as well.

    To get started, we’ll create two functions — warning for logging warnings to the console, and invariant for throwing an error — both if a given condition is not met.

    function warning(condition, message) { if (process.env.NODE_ENV === 'production' || condition) { return; } console.warn('useValidation: ' + message);
    function invariant(condition, message) { if (process.env.NODE_ENV === 'production' || condition) { return; } throw new Error('useValidation: ' + message);

    You want to use invariant if the error is going to crash your library (or render it useless), and warning for bad practices or other advice.

    When To Warn

    Deciding when to warn is pretty important. Too many, and you’re just annoying. Too few, and you let critical bugs ship to production. Therefore, we need to be smart with our warnings.

    Since our library accepts a pretty large configuration object, it makes sense to validate this somehow — at least while developing. We could solve it by using a type system like TypeScript or Flow, but that excludes all regular ol’ JavaScript users.

    Instead, let’s create a runtime schema checker, where we validate that the config contains the correct fields, and print relevant warnings.

    function validateConfigSchema(config) { if (process.env.NODE_ENV === 'production') { return; } if (typeof config === 'function') { config = config({}); } invariant( typeof config === 'object', `useValidation should be called with an object or a function returning an object. You passed a ${typeof config}.`, ); invariant( typeof config.fields === 'object', 'useValidation requires a `field` prop with an object containing the fields and their validators. Please refer to the documentation on usage:' ); invariant( Object.values(config.fields).every(field => typeof field === 'object'), 'useValidation requires that the `field` object only contains objects. It looks like yours isn\'t. Please refer to the documentation on usage:' ); warning( ['always', 'blur', 'submit', undefined].includes(config.showError), 'useValidation received an unsupported value in the `showError` prop. Valid values are "always", "blur" or "submit".' ) // And so on

    We could probably go on doing this for a while if we wanted to spend the time. And you should! It’s a great way to improve the developer experience of your app.

    You don’t have to be writing these by hand, however. There’s a browser-port of the popular object schema validation library joi that could help out with creating a really nice runtime validation check. Also, as previously mentioned, a type system would help catch configuration errors at compile time for the users that use that type system.

    Allow For Flexibility

    A good developer experience is in large part not getting in the way of the developers. Let’s look at a few ways we can improve that experience.

    Compose Conflicting Props

    First, our prop getters apply some props to our inputs and forms that can be accidentally overridden by our consumers. Instead, let’s add a prop override object to our prop getters, which will compose any conflicting props together.

    Here’s how we can implement this in our getFieldProps:

    getFieldProps: (fieldName, overrides = {}) => ({ onChange: e => { const { value } =; if (!config.fields[fieldName]) { return; } dispatch({ type: 'change', payload: { [fieldName]: value }, }); if (overrides.onChange) { overrides.onChange(e); } }, onBlur: e => { dispatch({ type: 'blur', payload: fieldName }); if (overrides.onBlur) { overrides.onBlur(e) } }, name: || fieldName, value: state.values[fieldName] || '',

    A similar approach can be followed in getFormProps.

    Help Avoid Prop Drilling

    Some forms might be large and split up into several components. Instead of making our consumers’ drill props down the tree, we should provide a context. This way, they can access all the stuff we return from our custom hook anywhere in the tree below.

    First, let’s create a ValidationContext with React’s createContext method:

    export const ValidationContext = React.createContext({});

    Next, let’s create a component ValidationProvider, that provides all the values from the useValidation hook in context instead:

    export const ValidationProvider = props => { const context = useValidation(props.config); return (  {props.children}  );

    Now, instead of calling useValidation directly, we’d wrap our form in a ValidationProvider component, and get access to the validation props (getFormProps, errors etc) by use of the useContext hook. You’d use it like this:

    Import React, { useContext } from 'react';
    import { ValidationContext } from './useValidation'; function UsernameForm(props) { const { getFieldProps, errors } = useContext(ValidationContext); return ( <> <input {...getFieldProps('username')} /> {errors.username && {errors.username}></span>} </> );

    This way, you get the best of both worlds! You get a simple hook for those simple scenarios, and you get the flexibility you need for those complex parts.

    Documentation Is Key 🔑

    Whenever I’m using a library I didn’t write myself, I love great documentation. But what should you focus on, and where should you document?

    A first step should be to put together a simple to understand README, with the most basic usage examples readily available. Andrew Healey wrote an amazing piece on how to write a good README, which I highly recommend you read.

    When you’ve created a good README to get people going, a documentation website might be a good idea. Here, you can put a more in-depth API documentation, recipes for typical use cases and a good ol’ FAQ.

    There are great tools out there for generating documentation websites. My favorite is docusaurus from Facebook (humble brag: we used it when creating the create-react-app website), but there are several good alternatives out there.

    We’re not going to go through how to write good documentation in this article. There are several good articles out there — even a community called “Write the Docs”. They have written a great guide to how you can get started with writing great documentation.


    Through this article series, we’ve created a pretty decent validation library. It has a pretty simple API, flexibility for when you need it, a good developer experience, and a lot of pretty dank features.

    We’ve gone through how we implemented things step by step, and I hope you got a deeper understanding of how you can make your own library, and how you make it something people would love to use.

    Please let me know in the comments what you think, and if there were some parts you got stuck on or had a hard time understanding. I’ll try my best to update the article as feedback trickles in.

    To end this article off — here’s the final version:

    Thanks for reading!

    Smashing Editorial (dm, yk, il)
    How to Create Identity Guidelines That Empower Your Clients

    I’ve never really enjoyed writing brand guidelines, I always felt it got in the way of the “real” design work i wanted to be doing. But I also really don’t enjoy designing a carefully thought out, beautifully executed logo only to see it used and abused by a poorly informed client. To work on creating a visual identity and then to send it out into the world with the equivalent of a hastily scrawled map on the back of a cigarette packet is woefully inadequate.

    Through research and conversations with some world class identity designers I’ve found a solution to helping clients use their new visual identity to their absolute – a pattern library. We’ve all seen the beautiful digital UI kits, pattern libraries and style guides created by the likes of Mailchimp for their digital products, well its time to start creating similar for identity guidelines.

    I’ve found the easiest solution is to establish and understand all the ways the identity is going to be used during the discovery stage. A real deep dive into what the client has in mind for the logo and second guessing uses they might not have thought of means there are no surprises and it can also really help inform the final design.

    Here are some guidelines I’ve been using recently – these will all be included in the final identity pattern library.

    For Use on Digital

    A logo has to be responsive these days, it needs to work on all screen sizes so undoubtedly there will be several different versions of the logo — a desktop version, a different more simplified version for small screen sizes, possibly one for tablets. You may need an even more simplified version for use on the favicon in different sizes and and in different colors for various browsers.

    For Use on Social Media

    When using the identity in social media remember one size does not fit all on the various platforms — find out which platforms your client uses or may use. have test accounts set up on all the major platforms so you can test the usage as you are designing it. Some platforms use square images some use round. Nobody wants those black edges when the wrong shaped jpg has been used in a profile pic. Mock up each social media platform page to demonstrate how to use the logo and on twitter include a suggested theme color. Also suggest image styles to use in the profile header.

    For Use in Emails

    What about emails, do they need a file specific for an email signature or a few different versions for Mailchimp. Consider using thumbnail mockups of a couple of different mail chimp layout scenarios so the client can see which logo to use where.  

    For Use on Imagery

    Does the logotype need to overlay imagery, at what screen size? Again maybe different versions for different size imagery, what about dark imagery and light imagery — show which version to use on which. Demonstrate the type of photography that would be a good fit for them and that would work well with their logo.

    For Use on Videos

    Which logo needs to be used on videos if the logo is overlaying a video what size and opacity should they use?

    For Use in Print

    Demonstrate how the variations of the logo can be used on different documents from business cards to brochures, what backgrounds should  the white logo version be used on and what background should the colored version be used on. Whether there are any elements of the document that can be used alone for example shapes or an ampersand used in the logo. These don’t have to be long drawn out full blown documents but thumbnails and mock ups. Things that will enable the client as much as possible. Explain why a certain layout will work best.

    Usage Variations

    Is there a logotype version or just a logomark, is there a stacked version or a version with a strapline. When should these be used? Will the strapline be used on its own. How will this work? What will it look like? Again show real life scenarios.

    Clear Labeling on Files

    Label the files clearly and demonstrate their use in real life scenarios through mock ups and detail which file name should be used for which scenario.


    Demonstrate the colors, contrast and variations and show how they can be used and explain why certain scenarios won’t work and demonstrate why. Explain when transparency is appropriate and when it isn’t. Think about what the client truly needs as opposed to what you’ve always sent out. Will they really need a black version of their logo? Might they use it incorrectly if you supply them with one? Explain when PNGs should be used and when Jpegs should be. Explain the color variations that will be experienced from print and digital. Include Hex, CMYK, RGB and Pantone where possible. explain why colors look different in print than digitally


    If type is used in the logo explain whether it’s appropriate to use it on other things such as websites, often it isn’t but I’ve seen clients use it because that is what there logo is in. So suggest typefaces that would work really well even if there is not a typeface used in the logo make suggestions for their other collateral.


    More than anything I’ve found that mocking up in situ scenarios has been the most effective way of enabling the client. Together with the use of clear and concise language — communication is key. Label files clearly and in a way that will make sense to a client and then reference these in your guidelines so they are not left guessing which one to use. As well as supplying the appropriate files its important to demonstrate each of these versions in the identity guidelines don’t leave them guessing.

    I know this seems like a huge amount of work but it is beneficial for everybody involved. The client will feel truly empowered and to go out and use the brand correctly, you will have provided a top notch service to your client, their beautiful new brand will be out in the world showcasing your stunning work  and you will have helped them create a sense of cohesion through everything which will not only reflect well on them but on you too.


    Featured image via DepositPhotos.

    Add Realistic Chalk and Sketch Lettering Effects with Sketch’it – only $5!

    p img {display:inline-block; margin-right:10px;}
    .alignleft {float:left;}
    p.showcase {clear:both;}
    body#browserfriendly p, body#podcast p, div#emailbody p{margin:0;}

    A Quick Look at the First Public Working Draft for Color Adjust Module 1

    We’ve been talking a lot about Dark Mode around here ever since Apple released it as a system setting in MacOS 10.14 and subsequently as part of Safari. It’s interesting because of both what it opens up as as far as design opportunities as well as tailoring user experience based on actual user preferences.

    This week, we got an Editor’s Draft for the Color Adjust Module Level 1 specification and the First Public Working Draft of it. All of this is a work-in-progress, but the progression of it has been interesting to track. The spec introduces three new CSS properties that help inform how much control the user agent should have when determining the visual appearance of a rendered page based on user preferences.

    color-scheme is the first property defined in the spec and perhaps the centerpiece of it. It accepts light and dark values which — as you may have guessed — correspond to Light Mode and Dark Mode preferences for operating systems that support them. And, for what it’s worth, we could be dealing with labels other than “Light” and “Dark” (e.g. “Day” and “Night”) but what we’re dealing with boils down to a light color scheme versus a dark one.


    This single property carries some important implications. For one, the idea is that it allows us to set styles based on a user’s system preferences which gives us fine-grained control over that experience.

    Another possible implication is that declaring the property at all enables the user agent to take some responsibility for determining an element’s colors, where declaring light or dark informs the user agent that an element is “aware” of color schemes and should be styled according to a preference setting matching the value. On the other hand, we can give the browser full control to determine what color scheme to use based on the user’s system preferences by using the auto value. That tells the browser that an element is “unaware” of color schemes and that the browser can determine how to proceed using the user preferences and a systems’s default styling as a guide.

    It’s worth noting at this point that we may also have a prefers-color-scheme media feature (currently in the Editor’s Draft for the Media Queries Level 5 specification) that also serves to let us detect a user’s preference and help gives us greater control of the user experience based on system preferences. Robin has a nice overview of it. The Color Adjust Module Level 1 Working Draft also makes mention of possibly using a color scheme value in a <meta> element to indicate color scheme support.

    There’s more to the property, of course, including an only keyword, chaining values to indicate an order of preference, and even an open-ended custom ident keyword. So definitely dig in there because there’s a lot to take in.

    Pretty interesting, right? Hopefully you’re starting to see how this draft could open up new possibilities and even impacts how we make design decisions. And that’s only the start because there are two more properties!

    • forced-color-adjust: This is used when we want to support color schemes but override the user agent’s default stylesheet with our own CSS. This includes a note about possibly merging this into color-adjust.
    • color-adjust: Unlike forcing CSS overrides onto the user agent, this property provides a hint to browsers that they can change color values based on the both the user’s preferences and other factors, such as screen quality, bandwidth, or whatever is “deem[ed] necessary and prudent for the output device.” Eric Bailey wrote up the possibilities this property could open up as far as use cases, enhanced accessibility, and general implementations.

    The current draft is sure to expand but, hey, this is where we get to be aware of the awesome work that W3C authors are doing, gain context for the challenges they face, and even contribute to the work. (See Rachel Andrew’s advice on making contributions.)

    The post A Quick Look at the First Public Working Draft for Color Adjust Module 1 appeared first on CSS-Tricks.

    Privacy Settings
    We use cookies to enhance your experience while using our website. If you are using our Services via a browser you can restrict, block or remove cookies through your web browser settings. We also use content and scripts from third parties that may use tracking technologies. You can selectively provide your consent below to allow such third party embeds. For complete information about the cookies we use, data we collect and how we process them, please check our Privacy Policy
    Consent to display content from Youtube
    Consent to display content from Vimeo
    Google Maps
    Consent to display content from Google