Tag: from

Moving from Vanilla JavaScript to a Reusable Vue Component

I recently wrote an article explaining how you can create a countdown timer using HTML, CSS and JavaScript. Now, let’s look at how we can make that a reusable component by porting it into Vue using basic features that the framework provides.

Why do this at all? Well there are few reasons, but two stand out in particular:

  • Keeping UI in sync with the timer state: If you look at the code from the first post,  it all lives in the timerInterval function, most noticeably the state management. Each time it runs (every second) we need to manually find the proper element on our document — whether it’s the time label or the remaining time path or whatever — and change either its value or an attribute. Vue comes with an HTML-based template syntax that allows you to declaratively bind the rendered DOM to the underlying Vue instance’s data. That takes all the burden of finding and updating proper UI elements so we can rely purely on the component instance’s properties.
  • Having a highly reusable component: The original example works fine when only one timer is present on our document, but imagine that you want to add another one. Oops! We rely the element’s ID to perform our actions and using the same ID on multiple instances would prevent them from working independently. That means we would have to assign different IDs for each timer. If we create a Vue component, all it’s logic is encapsulated and connected to that specific instance of the component. We can easily create 10, 20, 1,000 timers on a single document without changing a single line in the component itself!

Here’s the same timer we created together in the last post, but in Vue.

Template and styles

From the Vue docs:

Vue uses an HTML-based template syntax that allows you to declaratively bind the rendered DOM to the underlying Vue instance’s data. All Vue.js templates are valid HTML that can be parsed by spec-compliant browsers and HTML parsers.

Let’s create our component by opening a new file called BaseTimer.vue. Here’s the basic structure we need for that:

// Our template markup will go here <template> // ... </template>  // Our functional scripts will go here <script> // ... </script>  // Our styling will go here <style> // ... </style>

In this step, we will concentrate on the <template> and <style> sections. Let’s move our timer template to the <template> section and all our CSS to <style> section. The markup mostly consists of SVG and we can use the exact same code we used from the first article.

<template>   // The wrapper for the timer   <div class="base-timer">      // This all comes from the first article     <svg class="base-timer__svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">       <g class="base-timer__circle">         <circle class="base-timer__path-elapsed" cx="50" cy="50" r="45"></circle>         <path           id="base-timer-path-remaining"           stroke-dasharray="283"           class="base-timer__path-remaining $  {remainingPathColor}"           d="             M 50, 50             m -45, 0             a 45,45 0 1,0 90,0             a 45,45 0 1,0 -90,0           "         ></path>       </g>     </svg>      // The label showing the remaining time     <span       id="base-timer-label"       class="base-timer__label"     >       $  {formatTime(timeLeft)}     </span>    </div> </template>  // "scoped" means these styles will not leak out to other elements on the page <style scoped> .base-timer {   position: relative;   width: 100px;   height: 100px; } </style>

Let’s have a look at the template we just copied to identify where we can use our framework. There are few parts that are responsible for making our timer count down the time and show the remaining time.

  • stroke-dasharray: A value passed to the SVG <path> element that is responsible for holding the remaining time.
  • remainingPathColor: A CSS class responsible for changing the color of the timer’s circular ring, giving is a way to visually indicate that time is running out.
  • formatTime(timeLeft): A value responsible for showing how much time is left inside the timer

We can control our timer by manipulating those values.

Constants and variables

OK, let’s go down to our <script> section and see what Vue gives us out of the box to make our life easier. One thing it lets us do is define our constants up front, which keeps them scoped to the component.

In the last post, we spent a little time tweaking the stroke-dasharray  value to make sure the animation of the timer’s top layer (the ring that animates and changes color as time progresses) is perfectly in line with its bottom layer (the gray ring that indicates past time). We also defined “thresholds” for when the top layer should change colors (orange at 10 remaining seconds and red at five seconds). We also created constants for those colors.

We can move all of those directly into the <script> section:

<script> // A value we had to play with a bit to get right const FULL_DASH_ARRAY = 283; // When the timer should change from green to orange const WARNING_THRESHOLD = 10; // When the timer should change from orange to red const ALERT_THRESHOLD = 5;  // The actual colors to use at the info, warning and alert threshholds const COLOR_CODES = {   info: {     color: "green"   },   warning: {     color: "orange",     threshold: WARNING_THRESHOLD   },   alert: {     color: "red",     threshold: ALERT_THRESHOLD   } };  // The timer's starting point const TIME_LIMIT = 20; </script>

Now, let’s have a look at our variables:

let timePassed = 0; let timeLeft = TIME_LIMIT; let timerInterval = null; let remainingPathColor = COLOR_CODES.info.color;

We can identify two different types of variables here:

  1. Variables in which the values are directly re-assigned in our methods:
    • timerInterval: Changes when we start or stop the timer
    • timePassed: Changes each second when the timer is running
  2. Variables in which the values change when other variables change:
    • timeLeft: Changes when the value of timePassed changes
    • remainingPathColor: Changes when the value of timeLeft breaches the specified threshold

It is essential to identify that difference between those two types as it allows us to use different features of the framework. Let’s go through each of the type separately.

Variables in which values are directly re-assigned

Let’s think what we want to happen when we change the timePassed value. We want to calculate how much time is left, check if we should change the top ring’s color, and trigger re-render on a part of our view with new values. 

Vue comes with its own reactivity system that updates the view to match the new values of specific properties. To add a property to Vue’s reactivity system we need to declare that property on a data object in our component. By doing that,Vue will create a getter and a setter for each property that will track changes in that property and respond accordingly.

<script> // Same as before  export default {   data() {     return {       timePassed: 0,       timerInterval: null     };   } </script>

There are two important things we need to remember.

  1. We need to declare all reactive variables in our data object up front. That means if we know that a variable will exist but we don’t know what the value will be, we still need to declare it with some value. If we forgot to declare it in data it will not be reactive, even if it is added later.
  2. When declaring our data option object, we always need to return a new object instance (using return). This is vital because, if we don’t follow this rule, the declared properties will be shared between all instances of the component.

You can see that second issue in action:

Variables in which values change when other variable change

These variables rely on the value of another variable. For example, timeLeft relies purely on timePassed. In our original example that uses vanilla JavaScript, we were calculating that value in the interval that was responsible for changing the value of timePassed. With Vue, we can extract that value to a computed property.

computed property is a function that returns a value. These values are bound to the dependency values and only update when required. Even more importantly, computed properties are cached, meaning they remember the values that the computed property depends on and calculate the new value only if that dependent property value changed. If the value does not change, the previously cached value is returned.

<script> // Same as before  computed: {     timeLeft() {       return TIME_LIMIT - this.timePassed;     }   } } </script>

The function passed to the computed property must be a pure function. It can’t cause any side effects and must return a value. Also, the output value must only be dependent on the values passed into the function.

Now, we can move more logic to computed properties:

  • circleDasharray: This returns a value previously that is calculated in the setCircleDasharray method.
  • formattedTimeLeft: This returns a value from the formatTime method.
  • timeFraction: This is an abstraction of the calculateTimeFraction method.
  • remainingPathColor: This is an abstraction of the setRemainingPathColor method.
<script> // Same as before  computed: {     circleDasharray() {       return `$  {(this.timeFraction * FULL_DASH_ARRAY).toFixed(0)} 283`;     },      formattedTimeLeft() {       const timeLeft = this.timeLeft;       const minutes = Math.floor(timeLeft / 60);       let seconds = timeLeft % 60;       if (seconds < 10) {         seconds = `0$  {seconds}`;       }       return `$  {minutes}:$  {seconds}`;     },      timeLeft() {       return TIME_LIMIT - this.timePassed;     },      timeFraction() {       const rawTimeFraction = this.timeLeft / TIME_LIMIT;       return rawTimeFraction - (1 / TIME_LIMIT) * (1 - rawTimeFraction);     },      remainingPathColor() {       const { alert, warning, info } = COLOR_CODES;       if (this.timeLeft <= alert.threshold) {         return alert.color;       } else if (this.timeLeft <= warning.threshold) {         return warning.color;       } else {         return info.color;       }     }   } </script>

We now have all the values we need! But now we need to put them to use in our template.

Using data and computed properties in the template

Here’s where we left off with our template:

 <template>   <div class="base-timer">     <svg class="base-timer__svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">       <g class="base-timer__circle">         <circle class="base-timer__path-elapsed" cx="50" cy="50" r="45"></circle>         <path           id="base-timer-path-remaining"           stroke-dasharray="283"           class="base-timer__path-remaining $  {remainingPathColor}"           d="             M 50, 50             m -45, 0             a 45,45 0 1,0 90,0             a 45,45 0 1,0 -90,0           "         ></path>       </g>     </svg>     <span       id="base-timer-label"       class="base-timer__label"     >         $  {formatTime(timeLeft)}     </span>   </div> </template>

Let’s start with formatTime(timeLeft). How we can dynamically bind the rendered value to our formattedTimeLeftcomputed property?

Vue uses HTML-based template syntax that allowsus to declaratively bind the rendered DOM to the underlying data of the Vue instance. That means all properties are available in the template section. To render any of them, we use text interpolation using the “Mustache” syntax (double curly braces, or {{ }}).

<span   id="base-timer-label"   class="base-timer__label" >   {{ formattedTimeLeft }}  </span>

Next will be stroke-dasharray. We can see we don’t want to render that value. Instead, we want to change the value of the <path> attribute. Mustache cannot be used inside HTML attributes, but fear not! Vue comes with another way: the v-bind directive. We can bind a value to an attribute like this:

<path  v-bind:stroke-dasharray="circleDasharray"></path>

To facilitate the usage of that directive, we can also use a shorthand.

<path  :stroke-dasharray="circleDasharray"></path>

The last one is remainingPathColor, which adds a proper class to an element. We can do that using the same v-bind directive as above, but assign the value to the class attribute of an element.

<path  :class="remainingPathColor"></path>

Let’s have a look at our template after changes.

<template>   <div class="base-timer">     <svg class="base-timer__svg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">       <g class="base-timer__circle">         <circle class="base-timer__path-elapsed" cx="50" cy="50" r="45"></circle>         <path           :stroke-dasharray="circleDasharray"           class="base-timer__path-remaining"           :class="remainingPathColor"           d="             M 50, 50             m -45, 0             a 45,45 0 1,0 90,0             a 45,45 0 1,0 -90,0           "         ></path>       </g>     </svg>     <span class="base-timer__label">{{ formattedTimeLeft }}</span>   </div> </template>

We have our template ready, we moved all variables to data or computed, and we got rid off most of the methods by creating corresponding computed properties. We are still missing one vital part, though: we need to start our timer.

Methods and component lifecycle hooks

If we look at our startTimer method, we can see that all the calculations, changes in attributes, etc. happen in the interval.

function startTimer() {   timerInterval = setInterval(() => {     timePassed = timePassed += 1;     timeLeft = TIME_LIMIT - timePassed;     document.getElementById("base-timer-label").innerHTML = formatTime(       timeLeft     );     setCircleDasharray();     setRemainingPathColor(timeLeft);     if (timeLeft === 0) {       onTimesUp();     }   }, 1000); }

Since we’ve already moved all that logic into the computed property, all we need to do in our timerInterval is change the value of timePassed — the rest will happen magically in the computed properties

<script> // Same as before  methods: {   startTimer() {     this.timerInterval = setInterval(() => (this.timePassed += 1), 1000);   } } </script>

We have the method ready, but we still don’t call it anywhere. Each Vue component comes with a series of hooks that allows us to run a specific logic within a specific period of the component’s lifecycle. These are called lifecycle hooks. In our case, as we want to call our method immediately when the component gets loaded. That makes mounted the lifecycle hook what we want.

<script> // Same as before  mounted() {   this.startTimer(); },  // Same methods as before </script> 

That’s it, we just turned our timer into a consistent and reusable component using Vue!

Let’s say we now want to use this component in another component. That requires a few things:

  1. First, we import the component.
  2. Next, we register the component.
  3. Finally, we instantiate the component in the template.
// App.vue  import BaseTimer from "./components/BaseTimer"  export default {   components: {     BaseTimer   } }; 

That’s a wrap!

This example shows how we can move a component from vanilla JavaScript to a component-based front-end framework, like Vue. 

We can now treat the timer as a standalone component where all the markup, logic and styling is contained in a way that won’t leak out to or conflict with other elements. Components are often children of a larger parent component that assembles multiple components together — like a form or perhaps a card — where the parent’s properties can be accessed and shared. Here’s an example of the timer component where it’s taking orders from a parent component

I hope I got you interested in Vue and the power of components! I’d encourage you to go to Vue docs to get more detailed description of the features we used in our example. There’s so much Vue can do!

The post Moving from Vanilla JavaScript to a Reusable Vue Component appeared first on CSS-Tricks.


, , , , ,

What to Expect from the JAMstack in 2020

Brian Rinaldi interviewed a variety of folks, asking them the same questions about JAMstack development and the landscape recently:

  • Raymond Camden: I think we will see better competition from the bigger players.
  • Gift Egwuenu: I’m also looking forward to more job openings on the JAMstack.
  • Bryan Robinson: If you find yourself jumping through too many hoops, it might be time to explore a monolith architecture again.
  • Me: Blah blah blah, read the other ones from smart people 🙂
  • Tara Manicsic: there are more examples of enterprise applications creating more reliable user experiences, faster response times, and cutting their costs.

The post What to Expect from the JAMstack in 2020 appeared first on CSS-Tricks.


, , ,

Clips from my DEV AMA

I recently did an AMA over on DEV. Just taking the opportunity to port over some answers here like a good indiewebber.

If you were starting out as a front end dev in 2020, what would you say is the first thing you would learn and why?

You need to put yourself in a position where it’s your job to create and take care of a website. Even if that feels like a stretch for you early on. Get the domain, get the website on the public internet. Put your name on it. Now you’ve given yourself stakes, and you’ll learn technology because you must make your ideas come to life.

For me, 650 years ago, that was putting up a website for the ol’ college band. We needed a website! That sounded like fun to me, and I managed to struggle through buying a domain, hosting, and putting up a WordPress website. Then, over time, I learned front-end web technologies because I wanted to change up the design, change up the templates, add cool features, etc.

Get yourself a project and learn through the project.

How do you determine what you want to turn into a blog post and what you leave as a simple Tweet?

I usually won’t avoid the tweet. The tweet is usually a good proving ground for the blog post anyway. If nobody cared, eh, maybe not that good of a post. If it does get good engagement, it’s like the conversation around it is useful in the creation of the blog post. Plus, tweets are so easy to kick out the door. Blog posts, for me, on purpose, have a longer schedule that includes editing and scheduling and such.

Here’s an example tweet. Just a silly little UI experiment. I didn’t feel like waiting to blog about it to drop the demo. But from the Twitter thread, I got some interesting technical feedback, info about what parts people were most suprised by, and some other related ideas. That will, hopefully, lead to a much more robust blog post.

I even treat DEV like that, honestly. I wrote this blog post reaction quickly here, but then refined it for my own blog with some of the feedback.

Do you have a favorite CSS-Trick, where you were just like “wow”?

I think “scroll shadows” in CSS is one of my favorite CSS tricks of all time. It’s originally by Roman Komarov, but explained and improved by Lea Verou. I saw a tool the other day around the idea by Stefan Judis.

It’s a real mind-bender involving four-layered gradient backgrounds, each positioned, sized, and colored differently, and then behaviorally different regarding scrolling.

It’s not just a neat trick because it has real UX implications. Showing a shadow of where you can scroll is important UX. Consider this story of a recent design update in iOS that led to complete confusion around UI actions hidden behind a place you could scroll to, but had zero affordance on how to get there. (Happens to me all the time in Spotify, for the record.)

What would be your top 3 pieces of quick advice for developers trying to follow a similar path to growing their influence and exposure?

I think writing is literally the only way.

I can’t think of a developer with influence who has that influence for anything other than writing. Or if it’s not writing, then it’s a YouTube channel or some other form of creating public stuff.

How much do you see yourself personally playing with Houdini APIs as they are released? Which API are you most excited about (Painting, Layout, Typed OM, …)?

This super-low level stuff sometimes feels over my head. It’s hard for me to picture the industry implications of stuff like this just by looking at specs, ya know?

To me, it seems the Layout API has the most powerful potential.

What I’m imagining right now is that Houdini doesn’t affect normal day-to-day front-end developers like me that much. I won’t be writing much Houdini code. But I’ll use fancy things that other people create, because it does something useful for me. Just like most people don’t write their own libraries or have published npm packages — they just use them.

It’s fun to be wow’d by Houdini. If anyone is looking for that, make sure to look at Vincent De Oliveira’s showcase website.

What is your favorite thing about working at CodePen and/or CSS-Tricks?

You know what I really like? I like getting into the office every day and having a pretty decent amount of freedom of what I’m going to do that day. I’ll probably have meetings. I’ll probably have some stuff on the ol’ calendar. I’ll probably have some team expectations I’m trying to meet. But I also usually have plenty of time to pursue things that are interesting to me at the moment.

Sometimes I’m in the moment to drill through some emails. Sometimes I want to tinker with some demo that sounds like fun. Sometimes I want to write up a thought or record a video. Sometimes I want to plan something out or document something. Sometimes I want to talk something out with other people or do some pair programming.

I’m fortunate that I’m the boss (lol) and I put myself in that position on purpose so I have that freedom.

What is something that you wish we could add in CSS?

I feel like every time someone asks this we all should take every opportunity to scream Container Queries! until we get them.

The idea is that we should be able to write CSS that says, “When this element is this wide, this CSS should take effect.” And not just width, but whatever media queries we have at the page level already.

The best demo of a use case out there is Philip Walton’s page.

I want to write a card component that shuffles itself around based on how wide it is, not how wide the page is, because there isn’t always a direct connection between those two things (e.g. a card component can show up in a narrow sidebar on a large screen, but be full-width on a tablet or something).

Every component can be in a situation like that, so for the love of CSS, let me write media queries scoped to those components. I echo a lot of other people when I saw that if we had this, the vast majority of media queries we write would be these, not page-level.

Do you think it’s worth suggesting a { position: above-fold; }?

I’m not sure I’ve ever made a big fold-based decision once in my career. Not a big fan of that thinking. THERE IS A LINE IN WHICH THIS IMPORTANT MODULE MUST NOT CROSS, haha. Prioritizing the most important stuff to be higher up the page, sure. Websites don’t fold like newspapers.

Plus, we’ve got viewport units now, so if you absolutely need to position something in the top visible viewport area, you can.

Since you’ve been writing blog posts for so long, have you developed a process for writing one?

Sorta! It still feels pretty casual to me (let’s call my writing medium quality), so it’s not like I’m renting a cabin in the wilderness and finding inspiration in the sunsets and cheap whiskey.

  • I write down every blog post idea that comes to me. I try to keep that list fairly public but I also have a personal list where I can be even sloppier.
  • I put as much context into those lists as I can, so I can hope to summon up the same emotion that made me write it down in the first place. If I revisit the idea a week later and can’t, it’s probably not a very good idea.
  • I write up the post with as much context as I can. Light research is typically involved.
  • We have a lead editor on CSS-Tricks, so it’s reviewed by at least one person before being scheduled.

CSS or CSS-in-JS?

I see a ton of cool stuff happening in CSS-in-JS. I think it solves a lot of interesting problems for certain websites. For example, I very much like the idea of having the option to write styles that are scoped to a component programmatically, and thus are tree-shaken when the component isn’t used automatically.

But the web is a big place, and dare I say most websites aren’t built with JavaScript-powered component models. Thus, CSS-in-JS isn’t necessary or appropriate for a lot of sites.

Although, two things to be clear:

  • You can’t have CSS-in-JS without CSS. CSS-in-JS is still styles that are applied to elements. It doesn’t absolve you from learning CSS.
  • The CSS-in-JS landscape is wide. It’s a little hard to talk about so vaguely. Each project in the bucket of CSS-in-JS handles things a bit differently and how the styles are applied to the site is even quite wide. I think it sometimes gets lost in the arguments that some of the approaches literally make a CSS stylesheet that you link up like you would any other CSS — even Sass-produced CSS — which there doesn’t seem to be much argument about anymore.

The post Clips from my DEV AMA appeared first on CSS-Tricks.



Two Lessons I Learned From Making React Components

Here’s a couple of lessons I’ve learned about how not to build React components. These are things I’ve come across over the past couple of months and thought they might be of interest to you if you’re working on a design system, especially one with a bunch of legacy technical decisions and a lot of tech debt under the hood.

Lesson 1: Avoid child components as much as you can

One thing about working on a big design system with lots of components is that the following pattern eventually starts to become problematic real quick:

<Card>   <Card.Header>Title</Card.Header>   <Card.Body><p>This is some content</p></Card.Body> </Card>

The problematic parts are those child components, Card.Body and Card.Header. This example isn’t terrible because things are relatively simple — it’s when components get more complex that things can get bonkers. For example, each child component can have a whole series of complex props that interfere with the others.

One of my biggest pain points is with our Form components. Take this:

<Form>   <Input />   <Form.Actions>     <Button>Submit</Button>     <Button>Cancel</Button>   </Form.Actions> </Form>

I’m simplifying things considerably, of course, but every time an engineer wants to place two buttons next to each other, they’d import Form.Actions, even if there wasn’t a Form on the page. This meant that everything inside the Form component gets imported and that’s ultimately bad for performance. It just so happens to be bad system design implementation as well.

This also makes things extra difficult when documenting components because now you’ll have to ensure that each of these child components are documented too.

So instead of making Form.Actions a child component, we should’ve made it a brand new component, simply: FormActions (or perhaps something with a better name like ButtonGroup). That way, we don’t have to import Form all the time and we can keep layout-based components separate from the others.

I’ve learned my lesson. From here on out I’ll be avoiding child components altogether where I can.

Lesson 2: Make sure your props don’t conflict with one another

Mandy Michael wrote a great piece about how props can bump into one another and cause all sorts of confusing conflicts, like this TypeScript example:

interface Props {   hideMedia?: boolean   mediaIsEdgeToEdge?: boolean   mediaFullHeight?: boolean   videoInline?: boolean }

Mandy writes:

The purpose of these props are to change the way the image or video is rendered within the card or if the media is rendered at all. The problem with defining them separately is that you end up with a number of flags which toggle component features, many of which are mutually exclusive. For example, you can’t have an image that fills the margins if it’s also hidden.

This was definitely a problem for a lot of the components we inherited in my team’s design systems. There were a bunch of components where boolean props would make a component behave in all sorts of odd and unexpected ways. We even had all sorts of bugs pop up in our Card component during development because the engineers wouldn’t know which props to turn on and turn off for any given effect!

Mandy offers the following solution:

type MediaMode = 'hidden'| 'edgeToEdge' | 'fullHeight'  interface Props {   mediaMode: 'hidden'| 'edgeToEdge' | 'fullHeight' }

In short: if we combine all of these nascent options together then we have a much cleaner API that’s easily extendable and is less likely to cause confusion in the future.

That’s it! I just wanted to make a quick note about those two lessons. Here’s my question for you: What have you learned when it comes to making components or working on design systems?

The post Two Lessons I Learned From Making React Components appeared first on CSS-Tricks.


, , , , ,

Highlights from Chrome Dev Summit 2019

Ire Aderinokun has made another round-up summary of some things that piqued her attention during this year’s Chrome Dev Summit and there’s a lot of exciting news! There’s the :is selector (which Geoff wrote about a while back) as well as logical properties, updates to standard form elements, and the ability to check whether a user is on a 4G network or whether they have a data saving mode enabled.

If you want to catch up on all the talks then you can watch them on the Chrome Developer YouTube channel.

Direct Link to ArticlePermalink

The post Highlights from Chrome Dev Summit 2019 appeared first on CSS-Tricks.


, , , ,

How Do You Remove Unused CSS From a Site?

Here’s what I’d like you to know upfront: this is a hard problem. If you’ve landed here because you’re hoping to be pointed at a tool you can run that tells you exactly what CSS you can delete from your project, well… there are tools out there, but I’m warning you to be very careful with them because none of them can ever tell you the complete story.

I know what you want. You want to run the tool, delete what it tells you, and you have a faster site in 2.2 minutes. I’m sorry, but I’m going to disappoint you.

I think you should have a healthy level of skepticism for any tool like that. None of them are exactly lying to you — they often just don’t have enough information to give you results that are safe and actionable. That’s not to say you can’t use them or it can’t be done. Let’s take a walk.

The motivation

I imagine the #1 driver for the desire to remove unused CSS is this:

You used a CSS framework (e.g. Bootstrap), included the framework’s entire CSS file, and you only used a handful of the patterns it provides.

I can empathize with that. CSS frameworks often don’t provide simple ways to opt-in to only what you are using, and customizing the source to work that way might require a level of expertise that your team doesn’t have. That might even be the reason you reached for a framework to begin with.

Say you’re loading 100 KB of CSS. I’d say that’s a lot. (As I write, this site has ~23 KB, and there are quite a lot of pages and templates. I don’t do anything special to reduce the size.) You have a suspicion, or some evidence, that you aren’t using a portion of those bytes. I can see the cause for alarm. If you had a 100 KB JPG that you could compress to 20 KB by dropping it onto some tool, that’s awesome and totally worth it. But the gain in doing that for CSS is even more important because CSS is loaded in the head and is render blocking. The JPG is not.

😬 Looking at “coverage”

Chrome’s DevTools has a “Coverage” tab that will tell you how much of your CSS and JavaScript is in use. For example, if I visit the homepage of CSS-Tricks right now…

It tells me that 70.7% of my style.css file is unused. I imagine it’s right, and that the rest of the CSS is used elsewhere. I didn’t just dump a big style library onto this site; I wrote each line of that by hand, so I have my doubts that more than 2/3 of it is unused globally.

I assumed I could start “recording” then click around different areas of the site and watch that unused number go down as different pages with different HTML are rendered, but alas, when the page refreshes, so does the Coverage tab. It’s not very useful in getting a multi-page look at CSS coverage, unless you have a Single Page App I guess?

I hate to say it but I find looking at code coverage pretty useless. For me, it paints a dire picture of all this unused code on the site, which preys upon my doubts, but all I can do is worry about it.

This might be the very thing that’s given you the idea that unused CSS needs to be discovered and deleted in the first place.

My primary concern

My biggest concern is that you look at something like code coverage and see your unused lines:

And you go, Perfect! I’ll delete that CSS! And you do, only to find out it wasn’t unused at all and you caused big styling problems throughout the site. Here’s the thing: you don’t actually know if a CSS selector is unused unless you:

  1. check coverage on every single page of your entire site…
  2. while executing all JavaScript…
  3. under every possible combination of state…
  4. in every possible combination of media queries you’ve used.

Checking your homepage doesn’t count. Checking all your top-level pages doesn’t count. You gotta dig through every page, including states that aren’t always top-of-mind, not to mention all of the edge-case scenarios. Otherwise, you might end up deleting the dropdown styling for the credit card choice dropdown in the pop-up modal that appears for users with a disabled account who’ve logged in during their grace period that also have a gift card to apply.

This is too complex for automated tooling to promise their approach works perfectly, particularly when factoring in the unknowns of browser context (different screen sizes, different capabilities, different browsers) and third parties.

Here’s an example of my concern playing out:

PurifyCSS Online takes some URLs and instantly provides a copy-pasteable chunk of CSS to use

Here’s me dropping my css-tricks.com into PurifyCSS Online and getting new CSS.


On the left, CSS-Tricks as normal. On the right, I applied the new “purified” CSS, which deleted a bunch of CSS necessary for other pages.

It gave me the opportunity to put in other URLs (which is nice) but there are tens of thousands of URLs on CSS-Tricks. Many of them are fairly similar, but all of them have the potential of having selectors that are used. I get the impression it didn’t execute JavaScript, because anything that came onto the page via JavaScript was left unstyled. It even deleted my :hover states.

Perhaps you can see why my trust in these tools is so low.

Part of a build process

PurifyCSS is probably more regularly used as a build process tool rather than the online interface. Their docs have instructions for Grunt, Gulp, and webpack. For example, globbing files to check and process them:

var content = ['**/src/js/*.js', '**/src/html/*.html']; var css = ['**/src/css/*.css'];  var options = {   // Will write purified CSS to this file.   output: './dist/purified.css' };  purify(content, css, options);

This gives you a lot more opportunity for accuracy. That content blob could be a list of every single template, partial, and JavaScript file that builds your site. That might be a pain to maintain, but you’ll certainly get more accuracy. It doesn’t account for content in data stores (e.g. this blog post that lives in a database) and third-party JavaScript, but maybe that doesn’t matter to you or you can account for it some other way.

PurgeCSS, a competitor to PurifyCSS, warns about its comparison technique:

PurifyCSS can work with any file type, not just HTML or JavaScript. PurifyCSS works by looking at all of the words in your files and comparing them with the selectors in your CSS. Every word is considered a selector, which means that a lot of selectors can be erroneously consider used. For example, you may happen to have a word in a paragraph that matches a selector in your CSS.

So keep that in mind as well. It’s dumb in the way it compares potential selector matches, which is both clever and dangerous.

UnusedCSS is an online service that crawls your site for you

Manually configuring a tool to look at every page on your site from every angle is certainly a chore and something that will need to be kept in sync day-to-day as your codebase evolves. Interestingly, the online service UnusedCSS tries to overcome this burden by crawling the site itself based on a single URL you give it.

I signed up for the paid service and pointed it at CSS-Tricks. I admit, with just a glance at the results, it feels a lot more accurate to me:

It’s telling me I’m using 93% of my CSS, which feels more inline to me as hand-author of all the CSS on this site.

It also lets you download the cleaned file and offers lots of customization, like checking/unchecking selectors you actually want/don’t want (e.g. you see a class name it doesn’t think you need, but you know for sure you actually do need it) as well as prefixing and removing duplicate selectors.

I enjoyed the increased accuracy of the online crawling service, but there was a lot of noise, and I also can’t see how I’d incorporate it practically into a day-to-day build and release process.

Tooling is generally used post-processing

Say your CSS is built with Less or Sass, then uses a postprocessor to compile it into CSS. You’d probably incorporate automated unused CSS cleaning at the very end of whatever other CSS preprocessing you do. Like…

  1. Sass
  2. PostCSS / Autoprefixer
  3. [ Clean Unsued CSS ]
  4. Production CSS

That both makes sense and is slightly funny to me. You don’t actually fix the styling that generates unused CSS. Instead, you just wipe it away at the end of the build. I suppose JavaScript has been doing that kind of thing with tree shaking for a while, so there is a precedent, but it still feels weird to me because a CSS codebase is so directly hands-on. This setup almost encourages you to dump CSS wherever because there is no penalty for overdoing. It removes any incentive to understand how CSS is applied and used.

PurgeCSS is another tool that takes explicit input and gives you the results

PurgeCSS is another player in the unused CSS market. One tangential thing I like about it is that it clearly explains how it differs from other tools. For example, compared to PurifyCSS:

The biggest flaw with PurifyCSS is its lack of modularity. However, this is also its biggest benefit. PurifyCSS can work with any file type, not just HTML or JavaScript. PurifyCSS works by looking at all of the words in your files and comparing them with the selectors in your CSS. Every word is considered a selector, which means that a lot of selectors can be erroneously consider used. For example, you may happen to have a word in a paragraph that matches a selector in your CSS.

PurgeCSS fixes this problem by providing the possibility to create an extractor. An extractor is a function that takes the content of a file and extracts the list of CSS selectors used in it. It allows a perfect removal of unused CSS.

PurgeCSS seems like the big dog at the moment. Lots of people are using it and writing about it.

Despite PurgeCSS needing special configuration to work with Tailwind, it seems like Tailwind and PurgeCSS are two peas in a pod. In fact, their docs recommend using them together and provides a CLI for using it in a build process.

I believe the gist of it is this: Tailwind produces this big CSS file full of utility selectors. But they don’t intend for you to use the entire thing. You use these utility selectors in your HTML to do all your styling, then use PurgeCSS to look at all your HTML and shake out the unused utility selectors in your production CSS.

Still, it will be an ongoing maintenance issue to teach it about every single template on your site — JavaScript, HTML, or otherwise — while manually configuring anything that relies on third-party resources and knowing that any data that comes from a data store probably cannot be looked at during a build process, making it something to account for manually.

My favorite technique: have someone who is really familiar with your CSS codebase be aware of the problem and aim to fix it over time

Perhaps this feels like the approach of an old-timer who needs to get with the times, but hey, this just feels like the most practical approach to me. Since this problem is so hard, I think hard work is the answer to it. It’s understanding the problem and working toward a solution over time. A front-end developer that is intimately involved in your front end will have an understanding about what is used and usused in CSS-land after time and can whittle it down.

An extreme testing approach I’ve seen is using a (i.e. background-image: url(/is-this-being-used.gif?selector);) in the CSS block and then checking server logs over time to see if that image has been accessed. If it is accessed, it was used; if not, it wasn’t.

But perhaps my favorite tool in the potential toolbox is this:

Visual regression testing

You screenshot as much of your site as possible — like all of the most important pages and those pages manipulated into different states — plus across different browsers and screen sizes. Those screenshots are created from your master branch on Git.

Then, before any branches gets merged into Master, you take all those screenshots of them and compare those to the screenshots in master. Not manually, but programmatically.

That’s exactly what Percy does, so watch this:

There have been other stabs at visual regression testing tools over the years, but Percy is the only one I’ve seen that makes clear sense to me. I don’t just need to take screenshots; I want them compared so I can see visual differences between them. I don’t just want to see the differences; I want to approve or disapprove them. I also want that approval to block or allow merges and I want to be able to control the browser before the screenshot is taken. I don’t want to manually update the comparison images. That’s all bread-and-butter Percy stuff.

Full disclosure: Percy has sponsored things here on CSS-Tricks here before — including that video above — but not this post.

The relation to Atomic CSS and CSS-in-JS

I’m sure there are lots of people reading this that would say: I don’t have unused CSS because the tooling I use generates the exact CSS it needs and nothing more.

Hey, that’s kinda cool.

Maybe that’s Atomizer. Maybe that’s Tachyons that you also run through UnCSS and you are super careful about it. Maybe it’s the Tailwind + PurgeCSS combo that’s all the rage right now.

Maybe you tackle styles some other way. If you’re tightly coupling JavaScript components and styles, like React and Emotion, or even just using CSS modules with whatever, less unused CSS is an advantage of CSS-in-JS. And because tree-shaking and code-splitting come along for the ride in many JavaScript-based build processes, you not only have less CSS but only load what you need at the moment. There are tradeoffs to all this though.

How do you avoid unused CSS in future projects?

I think the future of styling is an intentional split between global and componentized styles. Most styles are scoped to components, but there are global styling choices that are made that take clear advantage of the cascade (e.g. global typography defaults).

If most styling is left scoped to components, I think there is less opportunity for unused styles to build up as it’s much easier to wrap your mind around a small block of HTML and a small block of CSS that directly relate to each other. And when components die or evolve, the styling dies or evolves with it. CSS bundles are made from components that are actually used.

CSS-in-JS solutions naturally head in this direction as styles are bound to components. That’s the main point, really. But it’s not required. I like the generic approach of CSS modules, which is pretty much entirely for style scoping and doesn’t mandate that you use some particular JavaScript framework.

If all that seems theoretical or out-of-reach, and you just have a Bootstrap site where you’re trying to reduce the size of all that Bootstrap CSS, I’d recommend starting by using Bootstrap from the source instead of the final default distributed bundle. The source is SCSS and built from a bunch of high-level includes, so if you don’t need particular parts of Bootstrap, you can remove them.

Removing dropdowns, badges, and breadcrumbs from Bootstrap before the build.

Good luck out there, gang.

The post How Do You Remove Unused CSS From a Site? appeared first on CSS-Tricks.


, , ,

The Amazingly Useful Tools from Yoksel

I find myself web searching for some tool by Yoksel at least every month. I figured I’d list out some of my favorites here in case you aren’t aware of them.

The post The Amazingly Useful Tools from Yoksel appeared first on CSS-Tricks.


, , , ,

Blocking Third-Party Hands from the Cookie Jar

Third-party cookies are set on your computer from domains other than the one that you’re actually on right now. For example, if I log into css-tricks.com, I’ll get a cookie from css-tricks.com that handles my authentication. But css-tricks.com might also load an image from some other site. A common tactic in online advertising is to render a “tracking pixel” image (well named, right?) that is used to track advertising impressions. That request to another site for the image (say, ad.doubleclick.com) also can set a cookie.

Eric Lawrence explains the issue:

The tracking pixel’s cookie is called a third party cookie because it was set by a domain unrelated to the page itself.

If you later visit B.textslashplain.com, which also contains a tracking pixel from ad.doubleclick.net, the tracking pixel’s cookie set on your visit to A.example.com is sent to ad.doubleclick.net, and now that tracker knows that you’ve visited both sites. As you browse more and more sites that contain a tracking pixel from the same provider, that provider can build up a very complete profile of the sites you like to visit, and use that information to target ads to you, sell the data to a data aggregation company, etc.

But times are a changin’. Eric goes on to explain the browser landscape:

The default stuff is the big deal, because all browsers offer some way to block third-party cookies. But of course, nobody actually does it. Jeremy:

It’s hard to believe that we ever allowed third-party cookies and scripts in the first place. Between them, they’re responsible for the worst ills of the World Wide Web.

2019 is the year we apparently reached the breaking point.

The post Blocking Third-Party Hands from the Cookie Jar appeared first on CSS-Tricks.


, , , ,

Get Geographic Information from an IP Address for Free

Say you need to know what country someone visiting your website is from, because you have an internationalized site and display different things based on that country. You could ask the user. You might want to have that functionality anyway to make sure your visitors have control, but surely they will appreciate it just being correct out of the gate, to the best of your ability.

There are no native web technologies that have this information. JavaScript has geolocation, but users would have to approve that, and even then you’d have to use some library to convert the coordinates into a more usable country. Even back-end languages, which have access to the IP address in a way that JavaScript doesn’t, don’t just automatically know the country of origin.


You have to ask some kind of service that knows this. The IP Geolocation API is that service, and it’s free.

You perform a GET against the API. You can do it right in the browser if you want to test it:


But you don’t just get the country. You get a whole pile of information you might need to use. I happen to be sitting in Canada and this is what I get for my IP:

{     "continent":"North America",    "address_format":"{{recipient}}\n{{street}}\n{{city}} {{region_short}} {{postalcode}}\n{{country}}",    "alpha2":"CA",    "alpha3":"CAN",    "country_code":"1",    "international_prefix":"011",    "ioc":"CAN",    "gec":"CA",    "name":"Canada",    "national_destination_code_lengths":[        3    ],    "national_number_lengths":[        10    ],    "national_prefix":"1",    "number":"124",    "region":"Americas",    "subregion":"Northern America",    "world_region":"AMER",    "un_locode":"CA",    "nationality":"Canadian",    "postal_code":true,    "unofficial_names":[        "Canada",       "Kanada",       "Canadá",       "カナダ"    ],    "languages_official":[        "en",       "fr"    ],    "languages_spoken":[        "en",       "fr"    ],    "geo":{        "latitude":56.130366,       "latitude_dec":"62.832908630371094",       "longitude":-106.346771,       "longitude_dec":"-95.91332244873047",       "max_latitude":83.6381,       "max_longitude":-50.9766,       "min_latitude":41.6765559,       "min_longitude":-141.00187,       "bounds":{           "northeast":{              "lat":83.6381,             "lng":-50.9766          },          "southwest":{              "lat":41.6765559,             "lng":-141.00187          }       }    },    "currency_code":"CAD",    "start_of_week":"sunday" }

With that information, I could easily decide to redirect to the Canadian version of my website, if I have one, or show prices in CAD, or offer a French translation, or whatever else I can think of.

Say you were in PHP. You could get the IP like…

function getUserIpAddr() {   if (!empty($  _SERVER['HTTP_CLIENT_IP'])) {     $  ip = $  _SERVER['HTTP_CLIENT_IP'];   } elseif (!empty($  _SERVER['HTTP_X_FORWARDED_FOR'])) {     $  ip = $  _SERVER['HTTP_X_FORWARDED_FOR'];   } else {     $  ip = $  _SERVER['REMOTE_ADDR'];   }   return $  ip; }

The cURL to get the information:

$  url = "https://api.ipgeolocationapi.com/geolocate/";  $  ch = curl_init();   curl_setopt($  ch, CURLOPT_RETURNTRANSFER, 1);  curl_setopt($  ch, CURLOPT_URL, $  url);  $  result = curl_exec($  ch); 

It comes back as JSON, so:

$  json = json_decode($  result);

And then $ json->{'name'}; will be “Canada” if I’m in Canada.

So I can do like:

if ($  json->{'name'} == "Canada") {   // serve index-ca.php } else {   // server index.php }

The post Get Geographic Information from an IP Address for Free appeared first on CSS-Tricks.


, , , ,

Random Notes from a JAMstack Roundtable

I hosted a JAMstack roundtable discussion at Web Unleashed this past weekend. Just a few random notes from that experience.

  • I was surprised at first that there really is confusion that the “M” in Jamstack stands for “Markdown” (the language that compiles to HTML) rather than “Markup” (the “M” in HTML, sometimes used interchangeably with HTML). It came up as legit confusion. Answer: Markdown isn’t required for JAMstack. The confusion comes from the idea that Markdown often goes hand-in-hand with static site generators which go hand-in-hand with JAMstack.
  • It occurred to me for the first time that every single site that is hosted on Netlify or GitHub Pages or an S3 bucket (“static hosting”) is JAMstack. SHAMstack, indeed! :). The static hosting (SH) part of JAMstack is, perhaps, the most important aspect.
  • A website that is a single index.html file with <div id="root"> and a bundle of JavaScript that client-site renders the rest of everything can be JAMstack. Assuming the data it needs is either baked in or coming from an API on some other server that isn’t the one that hosts that index.html file, it’s JAMstack.
  • There is a difference between technically JAMstack and spiritually JAMstack. The above is perhaps more technically and less spiritually. The latter wants you to pre-render more of the site than nothing.
  • Pre-rendering is nice because: it’s fast, it can be CDN-hosted, it’s secure, and it’s SEO-friendly. A lot of frameworks give it to you as part of what they do, so you might as well take advantage. Pre-rendering doesn’t mean static, JavaScript can still load and get fancy.
  • There is no denying that Static Site Generators and JAMstack are BFF. But JAMstack wants you to think bigger. What if you can’t render everything because you have 50,000 product pages and generation is too slow or otherwise impractical? No problem, you can prerender other pages but just a shell for the product pages and hit an API for product page data as needed. What if some pages just absolutely can’t be statically hosted? No problem, you can proxy the ones that can to a static server and leave the rest alone. Want to go all-in on the static hosting, but need servers for certain functionality? Consider serverless functions, which are sort of like the backend spiritual partner to static hosting.
  • People really want to know why. Why bother with this stuff at all? If you can build a site that does all the stuff you need with WordPress, why not just do that? I ended up defending my usage of WordPress from a feature perspective. If I had unlimited time and a fresh slate, even if I stay on WordPress as the CMS, I think I would likely head down a road of at least doing some pre-rendering if not totally de-coupling and building my own front-end and just using the data via APIs. But perhaps the most compelling answers to why come down to speed, security, and resiliency, all of which come along for the ride immediately when you go JAMstack. It provides a hell of a foundation to build on.

The post Random Notes from a JAMstack Roundtable appeared first on CSS-Tricks.


, , , ,