Number animation, as in, imagine a number changing from 1 to 2, then 2 to 3, then 3 to 4, etc. over a specified time. Like a counter, except controlled by the same kind of animation that we use for other design animation on the web. This could be useful when designing something like a dashboard, to bring a little pizazz to the numbers. Amazingly, this can now be done in CSS without much trickery. You can jump right to the new solution if you like, but first let’s look at how we used to do it.
One fairly logical way to do number animation is by changing the number in JavaScript. We could do a rather simple setInterval, but here’s a fancier answer with a function that accepts a start, end, and duration, so you can treat it more like an animation:
CodePen Embed Fallback
Keeping it to CSS, we could use CSS counters to animate a number by adjusting the count at different keyframes:
CodePen Embed Fallback
Another way would be to line up all the numbers in a row and animate the position of them only showing one at a time:
CodePen Embed Fallback
Some of the repetitive code in these examples could use a preprocessor like Pug for HTML or SCSS for CSS that offer loops to make them perhaps easier to manage, but use vanilla on purpose so you can see the fundamental ideas.
The New School CSS Solution
With recent support for CSS.registerProperty and @property, we can animate CSS variables. The trick is to declare the CSS custom property as an integer; that way it can be interpolated (like within a transition) just like any other integer.
Important Note: At the time of this writing, this @property syntax is only supported in Chrome ( and other Chromium core browsers like Edge and Opera), so this isn’t cross-browser friendly. If you’re building something Chrome-only (e.g. an Electron app) it’s useful right away, if not, wait. The demos from above are more widely supported.
The CSS content property can be used to display the number, but we still need to use counter to convert the number to a string because content can only output <string> values.
CodePen Embed Fallback
See how we can ease the animations just like any other animation? Super cool!
Typed CSS variables can also be used in @keyframes:
CodePen Embed Fallback
One downside? Counters only support integers. That means decimals and fractions are out of the question. We’d have to display the integer part and fractional part separately somehow.
Can we animate decimals?
It’s possible to convert a decimal (e.g. --number) to an integer. Here’s how it works:
Register an <integer> CSS variable ( e.g. --integer ), with the initial-value specified
Then use calc() to round the value: --integer: calc(var(--number))
In this case, --number will be rounded to the nearest integer and store the result into --integer.
Sometimes we just need the integer part. There is a tricky way to do it: --integer: max(var(--number) - 0.5, 0). This works for positive numbers. calc() isn’t even required this way.
We can extract the fractional part in a similar way, then convert it into string with counter (but remember that content values must be strings). To display concatenated strings, use following syntax:
Number animation, as in, imagine a number changing from 1 to 2, then 2 to 3, then 3 to 4, etc. over a specified time. Like a counter, except controlled by the same kind of animation that we use for other design animation on the web. This could be useful when designing something like a dashboard, to bring a little pizazz to the numbers. Amazingly, this can now be done in CSS without much trickery. You can jump right to the new solution if you like, but first let’s look at how we used to do it.
One fairly logical way to do number animation is by changing the number in JavaScript. We could do a rather simple setInterval, but here’s a fancier answer with a function that accepts a start, end, and duration, so you can treat it more like an animation:
CodePen Embed Fallback
Keeping it to CSS, we could use CSS counters to animate a number by adjusting the count at different keyframes:
CodePen Embed Fallback
Another way would be to line up all the numbers in a row and animate the position of them only showing one at a time:
CodePen Embed Fallback
Some of the repetitive code in these examples could use a preprocessor like Pug for HTML or SCSS for CSS that offer loops to make them perhaps easier to manage, but use vanilla on purpose so you can see the fundamental ideas.
The New School CSS Solution
With recent support for CSS.registerProperty and @property, we can animate CSS variables. The trick is to declare the CSS custom property as an integer; that way it can be interpolated (like within a transition) just like any other integer.
Important Note: At the time of this writing, this @property syntax is only supported in Chrome ( and other Chromium core browsers like Edge and Opera), so this isn’t cross-browser friendly. If you’re building something Chrome-only (e.g. an Electron app) it’s useful right away, if not, wait. The demos from above are more widely supported.
The CSS content property can be used to display the number, but we still need to use counter to convert the number to a string because content can only output <string> values.
CodePen Embed Fallback
See how we can ease the animations just like any other animation? Super cool!
Typed CSS variables can also be used in @keyframes:
CodePen Embed Fallback
One downside? Counters only support integers. That means decimals and fractions are out of the question. We’d have to display the integer part and fractional part separately somehow.
Can we animate decimals?
It’s possible to convert a decimal (e.g. --number) to an integer. Here’s how it works:
Register an <integer> CSS variable ( e.g. --integer ), with the initial-value specified
Then use calc() to round the value: --integer: calc(var(--number))
In this case, --number will be rounded to the nearest integer and store the result into --integer.
Sometimes we just need the integer part. There is a tricky way to do it: --integer: max(var(--number) - 0.5, 0). This works for positive numbers. calc() isn’t even required this way.
We can extract the fractional part in a similar way, then convert it into string with counter (but remember that content values must be strings). To display concatenated strings, use following syntax:
Let me show you a way I recently discovered to center a bunch of elements around what I call the pivot. I promise you that funky HTML is out of the question and you won’t need to know any bleeding-edge CSS to get the job done.
I’m big on word games, so I recently re-imagined the main menu of my website as a nod to crossword puzzles, with my name as the vertical word, and the main sections of my website across the horizontals.
Here’s how the design looks with the names of some colors instead:
And here’s a sample of the HTML that drives this puzzle:
In this example, the letter g is the pivot. See how it’s not at the halfway mark? That’s the beauty of this challenge.
We could apply an offset to each word using hard-coded CSS or inline custom properties and walk away. It certainly gets an award for being the most obvious way to solve the problem, but there’s a downside — in addition to the .pivot class, we’d have to specify an offset for every word. The voice in my head tells me that’s adding unnecessary redundancy, is less flexible, and requires extra baggage we don’t need every time we add or change a word.
Let’s take a step back instead and see how the puzzle looks without any balancing:
Imagine for a moment that we use display: none to hide all of the letters before the pivot; now all we can see are the pivots and everything after them:
With no further changes, our pivots would already be aligned. But we’ve lost the start of our words, and when we reintroduce the hidden parts, each word gets pushed out to the right and everything is out of whack again.
If we were to hide the trailing letters instead, we’d still be left with misaligned pivots:
All of this back-and-forth seems a bit pointless, but it reveals a symmetry to my problem. If we were to use a right-to-left (RTL) reading scheme, we’d have the opposite problem — we’d be able to solve the right side but the left would be all wrong.
Wouldn’t it be great if there was a way to have both sides line up at the same time?
As a matter of fact, there is.
Given we already have half a solution, let’s borrow a concept from algorithmics called divide and conquer. The general idea is that we can break a problem down into parts, and that by finding a solution for the parts, we’ll find a solution for the whole.
In that case, let’s break our problem down into the positioning of two parts. First is the “head” or everything before the pivot.
Next is the “tail” which is the pivot plus everything after it.
The flex display type will help us here; if you’re not familiar with it, flex is a framework for positioning elements in one-dimension. The trick here is to take advantage of the left and right ends of our container to enforce alignment. To make it work, we’ll swap the head and tail parts by using a smaller order property value on the tail than the head. The order property is used by flex to determine the sequence of elements in a flexible layout. Smaller numbers are placed earlier in the flow.
To distinguish the head and tail elements without any extra HTML, we can apply styles to the head part to all of the letters, after which we’ll make use of the cascading nature of CSS to override the pivot and everything after it using the subsequent-sibling selector .pivot ~ .letter.
Here’s how things look now:
Okay, so now the head is sitting flush up against the end of the tail. Hang on, don’t go kicking up a stink about it! We can fix this by applying margin: auto to the right of the last element in the tail. That just so happens to also be the last letter in the word which is now sitting somewhere in the middle. The addition of an auto margin serves to push the head away from the tail and all the way over to the right-hand side of our container.
Now we have something that looks like this:
The only thing left is stitch our pieces back together in the right order. This is easy enough to do if we apply position: relative to all of our letters and then chuck a left: 50% on the tail and a right: 50% on our head items.
Here’s a generalized version of the code we just used. As you can see, it’s just 15 lines of simple CSS:
It’s also feasible to use this approach for vertical layouts by setting the flex-direction to a column value. It should also be said that the same can be achieved by sticking the head and tail elements in their own wrappers — but that would require more markup and verbose CSS while being a lot less flexible. What if, for example, our back-end is already generating an unwrapped list of elements with dynamically generated classes?
Quite serendipitously, this solution also plays well with screen readers. Although we’re ordering the two sections backwards, we’re then shifting them back into place via relative positioning, so the final ordering of elements matches our markup, albeit nicely centered.
Screen readers preserve the element ordering as per the original markup.
Here’s the final example on CodePen:
CodePen Embed Fallback
Conclusion
Developers are better at balancing than acrobats. Don’t believe me? Think about it: many of the common challenges we face require finding a sweet spot between competing requirements ranging from performance and readability, to style and function, and even scalability and simplicity. A balancing act, no doubt.
But the point at which we find balance isn’t always midway between one thing and another. Balance is often found at some inexplicable point in between; or, as we’ve just seen, around an arbitrary HTML element.
So there you have it! Go and tell your friends that you’re the greatest acrobat around.
The moment I fell in love with front-end development was when I discovered the style.css file in WordPress themes. That’s where all the magic was (is!) to me. I could (can!) change a handful of lines in there and totally change the look and feel of a website. It’s an incredible game to play.
Back when I was cowboy-coding over FTP. Although I definitely wasn’t using CSS grid!
By fiddling with HTML and CSS, I can change the way you feel about a bit of writing. I can make you feel more comfortable about buying tickets to an event. I can increase the chances you share something with your friends.
That was well before anybody paid me money to be a front-end developer, but even then I felt the intoxicating mix of stimuli that the job offers. Front-end development is this expressive art form, but often constrained by things like the need to directly communicate messaging and accomplish business goals.
Front-end development is at the intersection of art and logic. A cross of business and expression. Both left and right brain. A cocktail of design and nerdery.
I love it.
Looking back at the courses I chose from middle school through college, I bounced back and forth between computer-focused classes and art-focused classes, so I suppose it’s no surprise I found a way to do both as a career.
The term “Front-End Developer” is fairly well-defined and understood. For one, it’s a job title. I’ll bet some of you literally have business cards that say it on there, or some variation like: “Front-End Designer,” “UX Developer,” or “UI Engineer.” The debate around what those mean isn’t particularly interesting to me. I find that the roles are so varied from job-to-job and company-to-company that job titles will never be enough to describe things. Getting this job is more about demonstrating you know what you’re doing more than anything else¹.
Chris Coyier Front-End Developer
The title variations are just nuance. The bigger picture is that as long as the job is building websites, front-enders are focused on the browser. Quite literally:
front-end = browsers
back-end = servers
Even as the job has changed over the decades, that distinction still largely holds.
As “browser people,” there are certain truths that come along for the ride. One is that there is a whole landscape of different browsers and, despite the best efforts of standards bodies, they still behave somewhat differently. Just today, as I write, I dealt with a bug where a date string I had from an API was in a format such that Firefox threw an error when I tried to use the .toISOString() JavaScript API on it, but was fine in Chrome. That’s just life as a front-end developer. That’s the job.
Even across that landscape of browsers, just on desktop computers, there is variance in how users use that browser. How big do they have the window open? Do they have dark mode activated on their operating system? How’s the color gamut on that monitor? What is the pixel density? How’s the bandwidth situation? Do they use a keyboard and mouse? One or the other? Neither? All those same questions apply to mobile devices too, where there is an equally if not more complicated browser landscape. And just wait until you take a hard look at HTML emails.
That’s a lot of unknowns, and the answers to developing for that unknown landscape is firmly in the hands of front-end developers.
Into the unknoooooowwwn. – Elsa
The most important aspect of the job? The people that use these browsers. That’s why we’re building things at all. These are the people I’m trying to impress with my mad CSS skills. These are the people I’m trying to get to buy my widget. Who all my business charts hinge upon. Who’s reaction can sway my emotions like yarn in the breeze. These users, who we put on a pedestal for good reason, have a much wider landscape than the browsers do. They speak different languages. They want different things. They are trying to solve different problems. They have different physical abilities. They have different levels of urgency. Again, helping them is firmly in the hands of front-end developers. There is very little in between the characters we type into our text editors and the users for whom we wish to serve.
Being a front-end developer puts us on the front lines between the thing we’re building and the people we’re building it for, and that’s a place some of us really enjoy being.
That’s some weighty stuff, isn’t it? I haven’t even mentioned React yet.
The “we care about the users” thing might feel a little precious. I’d think in a high functioning company, everyone would care about the users, from the CEO on down. It’s different, though. When we code a <button>, we’re quite literally putting a button into a browser window that users directly interact with. When we adjust a color, we’re adjusting exactly what our sighted users see when they see our work.
That’s not far off from a ceramic artist pulling a handle out of clay for a coffee cup. It’s applying craftsmanship to a digital experience. While a back-end developer might care deeply about the users of a site, they are, as Monica Dinculescu once told me in a conversation about this, “outsourcing that responsibility.”
We established that front-end developers are browser people. The job is making things work well in browsers. So we need to understand the languages browsers speak, namely: HTML, CSS, and JavaScript². And that’s not just me being some old school fundamentalist; it’s through a few decades of everyday front-end development work that knowing those base languages is vital to us doing a good job. Even when we don’t work directly with them (HTML might come from a template in another language, CSS might be produced from a preprocessor, JavaScript might be mostly written in the parlance of a framework), what goes the browser is ultimately HTML, CSS, and JavaScript, so that’s where debugging largely takes place and the ability of the browser is put to work.
CSS will always be my favorite and HTML feels like it needs the most love — but JavaScript is the one we really need to examine The last decade has seen JavaScript blossom from a language used for a handful of interactive effects to the predominant language used across the entire stack of web design and development. It’s possible to work on websites and writing nothing but JavaScript. A real sea change.
JavaScript is all-powerful in the browser. In a sense, it supersedes HTML and CSS, as there is nothing either of those languages can do that JavaScript cannot. HTML is parsed by the browser and turned into the DOM, which JavaScript can also entirely create and manipulate. CSS has its own model, the CSSOM, that applies styles to elements in the DOM, which JavaScript can also create and manipulate.
This isn’t quite fair though. HTML is the very first file that browsers parse before they do the rest of the work needed to build the site. That firstness is unique to HTML and a vital part of making websites fast.
In fact, if the HTML was the only file to come across the network, that should be enough to deliver the basic information and functionality of a site.
That philosophy is called Progressive Enhancement. I’m a fan, myself, but I don’t always adhere to it perfectly. For example, a <form> can be entirely functional in HTML, when it’s action attribute points to a URL where the form can be processed. Progressive Enhancement would have us build it that way. Then, when JavaScript executes, it takes over the submission and has the form submit via Ajax instead, which might be a nicer experience as the page won’t have to refresh. I like that. Taken further, any <button>outside a form is entirely useless without JavaScript, so in the spirit of Progressive Enhancement, I should wait until JavaScript executes to even put that button on the page at all (or at least reveal it). That’s the kind of thing where even those of us with the best intentions might not always toe the line perfectly. Just put the button in, Sam. Nobody is gonna die.
JavaScript’s all-powerfulness makes it an appealing target for those of us doing work on the web — particularly as JavaScript as a language has evolved to become even more powerful and ergonomic, and the frameworks that are built in JavaScript become even more-so. Back in 2015, it was already so clear that JavaScript was experiencing incredible growth in usage, Matt Mullenweg, co-founder of WordPress, gave the developer world homework: “Learn JavaScript Deeply”³. He couldn’t have been more right. Half a decade later, JavaScript has done a good job of taking over front-end development. Particularly if you look at front-end development jobs.
While the web almanac might show us that only 5% of the top-zillion sites use React compared to 85% including jQuery, those numbers are nearly flipped when looking around at front-end development job requirements.
I’m sure there are fancy economic reasons for all that, but jobs are as important and personal as it gets for people, so it very much matters.
So we’re browser people in a sea of JavaScript building things for people. If we take a look at the job at a practical day-to-day tasks level, it’s a bit like this:
Translate designs into code
Think in terms of responsive design, allowing us to design and build across the landscape of devices
Build systemically. Construct components and patterns, not one-offs.
Apply semantics to content
Consider accessibility
Worry about the performance of the site. Optimize everything. Reduce, reuse, recycle.
Just that first bullet point feels like a college degree to me. Taken together, all of those points certainly do.
This whole list is a bit abstract though, so let’s apply it to something we can look at. What if this website was our current project?
Our brains and fingers go wild!
Let’s build the layout with CSS grid.
What fonts are those? Do we need to load them in their entirety or can we subset them? What happens as they load in? This layout feels like it will really suffer from font-shifting jank.
There are some repeated patterns here. We should probably make a card design pattern. Every website needs a good card pattern.
That’s a gorgeous color scheme. Are the colors mathematically related? Should we make variables to represent them individually or can we just alter a single hue as needed? Are we going to use custom properties in our CSS? Colors are just colors though, we might not need the cascading power of them just for this. Should we just use Sass variables? Are we going to use a CSS preprocessor at all?
The source order is tricky here. We need to order things so that they make sense for a screen reader user. We should have a meeting about what the expected order of content should be, even if we’re visually moving things around a bit with CSS grid.
The photographs here are beautifully shot. But some of them match the background color of the site… can we get away with alpha-transparent PNGs here? Those are always so big. Can any next-gen formats help us? Or should we try to match the background of a JPG with the background of the site seamlessly. Who’s writing the alt text for these?
There are some icons in use here. Inline SVG, right? Certainly SVG of some kind, not icon fonts, right? Should we build a whole icon system? I guess it depends on how we’re gonna be building this thing more broadly. Do we have a build system at all?
What’s the whole front-end plan here? Can I code this thing in vanilla HTML, CSS, and JavaScript? Well, I know I can, but what are the team expectations? Client expectations? Does it need to be a React thing because it’s part of some ecosystem of stuff that is already React? Or Vue or Svelte or whatever? Is there a CMS involved?
I’m glad the designer thought of not just the “desktop” and “mobile” sizes but also tackled an in-between size. Those are always awkward. There is no interactivity information here though. What should we do when that search field is focused? What gets revealed when that hamburger is tapped? Are we doing page-level transitions here?
A lot of those things have been our jobs forever though. We’ve been asking and answering these questions on every website we’ve built for as long as we’ve been doing it. There are different challenges on each site, which is great and keeps this job fun, but there is a lot of repetition too.
Allow me to get around to the title of this article.
While we’ve been doing a lot of this stuff for ages, there is a whole pile of new stuff we’re starting to be expected to do, particularly if we’re talking about building the site with a modern JavaScript framework. All the modern frameworks, as much as they like to disagree about things, agree about one big thing: everything is a component. You nest and piece together components as needed. Even native JavaScript moves toward its own model of Web Components.
I like it, this idea of components. It allows you and your team to build the abstractions that make the most sense to you and what you are building.
Your Card component does all the stuff your card needs to do. Your Form component does forms how your website needs to do forms. But it’s a new concept to old developers like me. Components in JavaScript have taken hold in a way that components on the server-side never did. I’ve worked on many a WordPress website where the best I did was break templates into somewhat arbitrary include() statements. I’ve worked on Ruby on Rails sites with partials that take a handful of local variables. Those are useful for building re-usable parts, but they are a far cry from the robust component models that JavaScript frameworks offer us today.
All this custom component creation makes me a site-level architect in a way that I didn’t use to be. Here’s an example. Of course I have a Button component. Of course I have an Icon component. I’ll use them in my Card component. My Card component lives in a Grid component that lays them out and paginates them. The whole page is actually built from components. The Header component has a SearchBar component and a UserMenu component. The Sidebar component has a Navigation component and an Ad component. The whole page is just a special combination of components, which is probably based on the URL, assuming I’m all-in on building our front-end with JavaScript. So now I’m dealing with URLs myself, and I’m essentially the architect of the entire site. [Sweats profusely]
Like I told ya, a whole pile of new responsibility.
Components that are in charge of displaying content are almost certainly not hard-coded with data in them. They are built to be templates. They are built to accept data and construct themselves based on that data. In the olden days, when we were doing this kind of templating, the data has probably already arrived on the page we’re working on. In a JavaScript-powered app, it’s more likely that that data is fetched by JavaScript. Perhaps I’ll fetch it when the component renders. In a stack I’m working with right now, the front end is in React, the API is in GraphQL and we use Apollo Client to work with data. We use a special “hook” in the React components to run the queries to fetch the data we need, and another special hook when we need to change that data. Guess who does that work? Is it some other kind of developer that specializes in this data layer work? No, it’s become the domain of the front-end developer.
Speaking of data, there is all this other data that a website often has to deal with that doesn’t come from a database or API. It’s data that is really only relevant to the website at this moment in time.
Which tab is active right now?
Is this modal dialog open or closed?
Which bar of this accordion is expanded?
Is this message bar in an error state or warning state?
How many pages are you paginated in?
How far is the user scrolled down the page?
Front-end developers have been dealing with that kind of state for a long time, but it’s exactly this kind of state that has gotten us into trouble before. A modal dialog can be open with a simple modifier class like <div class="modal is-open"> and toggling that class is easy enough with .classList.toggle(".is-open"); But that’s a purely visual treatment. How does anything else on the page know if that modal is open or not? Does it ask the DOM? In a lot of jQuery-style apps of yore, yes, it would. In a sense, the DOM became the “source of truth” for our websites. There were all sorts of problems that stemmed from this architecture, ranging from a simple naming change destroying functionality in weirdly insidious ways, to hard-to-reason-about application logic making bug fixing a difficult proposition.
Front-end developers collectively thought: what if we dealt with state in a more considered way? State management, as a concept, became a thing. JavaScript frameworks themselves built the concept right in, and third-party libraries have paved and continue to pave the way. This is another example of expanding responsibility. Who architects state management? Who enforces it and implements it? It’s not some other role, it’s front-end developers.
There is expanding responsibility in the checklist of things to do, but there is also work to be done in piecing it all together. How much of this state can be handled at the individual component level and how much needs to be higher level? How much of this data can be gotten at the individual component level and how much should be percolated from above? Design itself comes into play. How much of the styling of this component should be scoped to itself, and how much should come from more global styles?
It’s no wonder that design systems have taken off in recent years. We’re building components anyway, so thinking of them systemically is a natural fit.
Let’s look at our design again:
A bunch of new thoughts can begin!
Assuming we’re using a JavaScript framework, which one? Why?
Can we statically render this site, even if we’re building with a JavaScript framework? Or server-side render it?
Where are those recipes coming from? Can we get a GraphQL API going so we can ask for whatever we need, whenever we need it?
Maybe we should pick a CMS that has an API that will facilitate the kind of front-end building we want to do. Perhaps a headless CMS?
What are we doing for routing? Is the framework we chose opinionated or unopinionated about stuff like this?
What are the components we need? A Card, Icon, SearchForm, SiteMenu, Img… can we scaffold these out? Should we start with some kind of design framework on top of the base framework?
What’s the client state we might need? Current search term, current tab, hamburger open or not, at least.
Is there a login system for this site or not? Are logged in users shown anything different?
Is there are third-party componentry we can leverage here?
Maybe we can find one of those fancy image components that does blur-up loading and lazy loading and all that.
Those are all things that are in the domain of front-end developers these days, on top of everything that we already need to do. Executing the design, semantics, accessibility, performance… that’s all still there. You still need to be proficient in HTML, CSS, JavaScript, and how the browser works. Being a front-end developer requires a haystack of skills that grows and grows. It’s the natural outcome of the web getting bigger. More people use the web and internet access grows. The economy around the web grows. The capability of browsers grows. The expectations of what is possible on the web grows. There isn’t a lot shrinking going on around here.
We’ve already reached the point where most front-end developers don’t know the whole haystack of responsibilities. There are lots of developers still doing well for themselves being rather design-focused and excelling at creative and well-implemented HTML and CSS, even as job posts looking for that dwindle.
There are systems-focused developers and even entire agencies that specialize in helping other companies build and implement design systems. There are data-focused developers that feel most at home making the data flow throughout a website and getting hot and heavy with business logic. While all of those people might have “front-end developer” on their business card, their responsibilities and even expectations of their work might be quite different. It’s all good, we’ll find ways to talk about all this in time.
In fact, how we talk about building websites has changed a lot in the last decade. Some of my early introduction to web development was through WordPress. WordPress needs a web server to run, is written in PHP, and stores it’s data in a MySQL database. As much as WordPress has evolved, all that is still exactly the same. We talk about that “stack” with an acronym: LAMP, or Linux, Apache, MySQL and PHP. Note that literally everything in the entire stack consists of back-end technologies. As a front-end developer, nothing about LAMP is relevant to me.
But other stacks have come along since then. A popular stack was MEAN (Mongo, Express, Angular and Node). Notice how we’re starting to inch our way toward more front-end technologies? Angular is a JavaScript framework, so as this stack gained popularity, so too did talking about the front-end as an important part of the stack. Node and Express are both JavaScript as well, albeit the server-side variant.
The existence of Node is a huge part of this story. Node isn’t JavaScript-like, it’s quite literally JavaScript. It makes a front-end developer already skilled in JavaScript able to do server-side work without too much of a stretch.
“Serverless” is a much more modern tech buzzword, and what it’s largely talking about is running small bits of code on cloud servers. Most often, those small bits of code are in Node, and written by JavaScript developers. These days, a JavaScript-focused front-end developer might be writing their own serverless functions and essentially being their own back-end developer. They’ll think of themselves as full-stack developers, and they’ll be right.
Shawn Wang coined a term for a new stack this year: STAR or Design System, TypeScript, Apollo, and React. This is incredible to me, not just because I kind of like that stack, but because it’s a way of talking about the stack powering a website that is entirely front-end technologies. Quite a shift.
I apologize if I’ve made you feel a little anxious reading this. If you feel like you’re behind in understanding all this stuff, you aren’t alone.
In fact, I don’t think I’ve talked to a single developer who told me they felt entirely comfortable with the entire world of building websites. Everybody has weak spots or entire areas where they just don’t know the first dang thing. You not only can specialize, but specializing is a pretty good idea, and I think you will end up specializing to some degree whether you plan to or not. If you have the good fortune to plan, pick things that you like. You’ll do just fine.
The only constant in life is change.
– Heraclitus
– Motivational Poster
– Chris Coyier
¹ I’m a white dude, so that helps a bunch, too. ↩️ ² Browsers speak a bunch more languages. HTTP, SVG, PNG… The more you know the more you can put to work! ↩️ ³ It’s an interesting bit of irony that WordPress websites generally aren’t built with client-side JavaScript components. ↩️
AWS Amplify is a collection of tools from AWS to help you build applications.
Allow me to set the stage here to try to make that as clear as I know how. I have a friend (true story) who wants to build an app centered around physical training. His wife is a physical trainer, and they think perhaps there is some money to be made. It’s not entirely specced out, but perhaps the app sells access to personalized training programs, offers customized diets, exercise videos, and does the scheduling for one-on-one consultations. Sounds smart to me! Assuming they prove out the idea to some degree, it’s time to put their development skills to work and get to building.
A lot of the needs of an app like this map directly and easily to Amplify. A developer starting to plan might think like this:
We need to host this somewhere… Amplify has Static Web Hosting. And it’s fully featured with the fancy DX we’re starting to except these days: I connect a Git repo, and it will not only do deployment to CDN-backed global static hosting based on commits, but it will run my CI/CD (e.g. run tests) and give me URLs for previewing feature branches. You do all this with the AWS Amplify Console.
We need to do user authentication... The whole point here is that users can log in to get access to their stuff. Amplify helps with this (it’s Amazon Cognito built-in), which allows for typical sign-up/sign-in/forgot-password stuff, but also all the social login stuff you would expect. This is an example of what Amplify does: it helps abstract and build out underlying cloud services with minimal code.
We need data storage… Ideally, it’s managed with GraphQL because my modern front-end really benefits from that (perhaps it’s a React app). Amplify has that. It’s AWS AppSync built-in, which means you can use any type of data store, but get amazing features on top, like the GraphQL endpoints, realtime data syncing, and offline support.
That’s just the basics. All of that is extremely well-covered.
How do we set all this stuff up? This is one of the best parts: there is a CLI to help do everything. For example, about that data storage stuff, how do we get going with that? Once the CLI is installed and we’ve run amplify init in the project, we do amplify add api and we’ll be walked through it.
Now for this physical training app, we’ll need some static file storage as well. Maybe all the users have custom avatars, and the videos themselves need protected hosting. Well, we’re in AWS land here, so S3 buckets are a perfect fit. How? amplify add storage and we’ll be walked through it and of course, there are docs.
Impressive, really. We can build almost this entire thing with Amplify.
The one time we might have to reach out to another service is to handle payments. Stripe is usually the first choice of developers because of their great DX and robust APIs. They are built exactly for apps like this. We’d do our communicating with Stripe APIs over serverless functions. And guess what? We’re in AWS land here, so we have access to Lambdas, the best serverless function provider there is. The trick is that we can have our GraphQL setup, via AppSync, call a Lambda which can communicate with any outside API. Fortunately, there is a detailed walkthrough here from Ramon Postulart.
Amplify is a helper. AWS offers tons of cloud services. Amplify helps you tie them together and get started using the important ones that you need.
The static hosting is the foundation for a web project. This is a Jamstack approach. But even that isn’t required, you can, for example, build an iOS app with the tools.
AWS is the biggest cloud provider in the world and powers many of the world’s biggest websites. You can build a personal project here and typically do it under the free tier, but you’ll never need to worry about scaling. You’re at the right place for scaling.
There is a lot to explore. If you wake up one day and want to add push notifications or explore something like machine learning, that stuff is there too.
If you’ve read this far, I think this quick high-level video will land better:
HTTP requests are a crucial part of any web application that’s communicating with a back-end server. The front end needs some data, so it asks for it via a network HTTP request (or Ajax, as it tends to be called), and the server returns an answer. Almost every website these days does this in some fashion.
With a larger site, we can expect to see more of this. More data, more APIs, and more special circumstances. As sites grow like this, it is important to stay organized. One classic concept is DRY (short for Don’t Repeat Yourself), which is the process of abstracting code to prevent repeating it over and over. This is ideal because it often allows us to write something once, use it in multiple places, and update in a single place rather than each instance.
We might also reach for libraries to help us. For Ajax, axios is a popular choice. You might already be familiar with it, and even use it for things like independent POST and GET requests while developing.
Installation and the basics
It can be installed using npm (or yarn):
npm install axios
An independent POST request using Axios looks like this:
Native JavaScript has multiple ways of doing JavaScript too. Notably, fetch(). So why use a library at all? Well, for one, error handling in fetch is pretty wonky. You’ll have a better time with axios right out of the gate with that. If you’d like to see a comparison, we have an article that covers both and an article that talks about the value of abstraction with stuff like this.
Another reason to reach for axios? It gives us more opportunities for DRYness, so let’s look into that.
Global config
We can set up a global configuration (e.g. in our main.js file) that handles all application requests using a standard configuration that is set through a default object that ships with axios.
This object contains:
baseURL: A relative URL that acts as a prefix to all requests, and each request can append the URL
headers: Custom headers that can be set based on the requests
timeout: The point at which the request is aborted, usually measured in milliseconds. The default value is 0, meaning it’s not applicable.
withCredentials: Indicates whether or not cross-site Access-Control requests should be made using credentials. The default is false.
responseType: Indicates the type of data that the server will return, with options including json (default), arraybuffer, document, text, and stream.
responseEncoding: Indicates encoding to use for decoding responses. The default value is utf8.
xsrfCookieName: The name of the cookie to use as a value for XSRF token, the default value is XSRF-TOKEN.
xsrfHeaderName: The name of the HTTP header that carries the XSRF token value. The default value is X-XSRF-TOKEN.
maxContentLength: Defines the max size of the HTTP response content in bytes allowed
maxBodyLength: Defines the max size of the HTTP request content in bytes allowed
Most of time, you’ll only be using baseURL, header, and maybe timeout. The rest of them are less frequently needed as they have smart defaults, but it’s nice to know there are there in case you need to fix up requests.
This is the DRYness at work. For each request, we don’t have to repeat the baseURL of our API or repeat important headers that we might need on every request.
Here’s an example where our API has a base, but it also has multiple different endpoints. First, we set up some defaults:
/ main.js
import axios from 'axios';
axios.defaults.baseURL = 'https://axios-app.firebaseio.com' // the prefix of the URL
axios.defaults.headers.get['Accept'] = 'application/json' // default header for all get request
axios.defaults.headers.post['Accept'] = 'application/json' // default header for all POST request
Then, in a component, we can use axios more succinctly, not needing to set those headers, but still having an opportunity to customize the final URL endpoint:
// form.js component
import axios from 'axios';
export default {
methods : {
onSubmit () {
// The URL is now https://axios-app.firebaseio.com/users.json
axios.post('/users.json', formData)
.then(res => console.log(res))
.catch(error => console.log(error))
}
}
}
Note: This example is in Vue, but the concept extends to any JavaScript situation.
Custom instance
Setting up a “custom instance” is similar to a global config, but scoped to specified components. So, it’s still a DRY technique, but with hierarchy.
We’ll set up our custom instance in a new file (let’s call it authAxios.js) and import it into the “concern” components.
Interceptors helps with cases where the global config or custom instance might be too generic, in the sense that if you set up an header within their objects, it applies to the header of every request within the affected components. Interceptors have the ability to change any object properties on the fly. For instance, we can send a different header (even if we have set one up in the object) based on any condition we choose within the interceptor.
Interceptors can be in the main.js file or a custom instance file. Requests are intercepted after they’ve been sent out and allow us to change how the response is handled.
// Add a request interceptor
axios.interceptors.request.use(function (config) {
// Do something before request is sent, like we're inserting a timeout for only requests with a particular baseURL
if (config.baseURL === 'https://axios-app.firebaseio.com/users.json') {
config.timeout = 4000
} else {
return config
}
console.log (config)
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(function (response) {
// Do something with response data like console.log, change header, or as we did here just added a conditional behaviour, to change the route or pop up an alert box, based on the reponse status
if (response.status === 200 || response.status 201) {
router.replace('homepage') }
else {
alert('Unusual behaviour')
}
console.log(response)
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
Interceptors, as the name implies, intercept both requests and responses to act differently based on whatever conditions are provided. For instance, in the request interceptor above, we inserted a conditional timeout only if the requests have a particular baseURL. For the response, we can intercept it and modify what we get back, like change the route or have an alert box, depending on the status code. We can even provide multiple conditions based on different error codes.
Interceptors will prove useful as your project becomes larger and you start to have lots of routes and nested routes all communicating to servers based on different triggers. Beyond the conditions I set above, there are many other situations that can warrant the use of interceptors, based on your project.
Interestingly, we can eject an interceptor to prevent it from having any effect at all. We’ll have to assign the interceptor to a variable and eject it using the appropriately named eject method.
const reqInterceptor = axios.interceptors.request.use(function (config) {
// Do something before request is sent, like we're inserting a timeout for only requests with a particular baseURL
if (config.baseURL === 'https://axios-app.firebaseio.com/users.json') {
config.timeout = 4000
} else {
return config
}
console.log (config)
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
// Add a response interceptor
const resInterceptor = axios.interceptors.response.use(function (response) {
// Do something with response data like console.log, change header, or as we did here just added a conditional behaviour, to change the route or pop up an alert box, based on the reponse status
if (response.status === 200 || response.status 201) {
router.replace('homepage')
} else {
alert('Unusual behaviour')
}
console.log(response)
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
axios.interceptors.request.eject(reqInterceptor);
axios.interceptors.request.eject(resInterceptor);
Although it’s less commonly used, it’s possible to put and interceptor into a conditional statement or remove one based on some event.
Hopefully this gives you a good idea about the way axios works as well as how it can be used to keep API requests DRY in an application. While we scratched the surface by calling out common use cases and configurations, axis has so many other advantages you can explore in the documentation, including the ability to cancel requests and protect against cross-site request forgery , among other awesome possibilities.
The <canvas> element in HTML and Canvas API in JavaScript combine to form one of the main raster graphics and animation possibilities on the web. A common canvas use-case is programmatically generating images for websites, particularly games. That’s exactly what I’ve done in a website I built for playing Solitaire. The cards, including all their movement, is all done in canvas.
In this article, let’s look specifically at animation in canvas and techniques to make them look smoother. We’ll look specifically at easing transitions — like “ease-in” and “ease-out” — that do not come for free in canvas like they do in CSS.
Let’s start with a static canvas. I’ve drawn to the canvas a single playing card that I grabbed out of the DOM:
CodePen Embed Fallback
Let’s start with a basic animation: moving that playing card on the canvas. Even for fairly basic things like requires working from scratch in canvas, so we’ll have to start building out functions we can use.
First, we’ll create functions to help calculate X and Y coordinates:
function getX(params) {
let distance = params.xTo - params.xFrom;
let steps = params.frames;
let progress = params.frame;
return distance / steps * progress;
}
function getY(params) {
let distance = params.yTo - params.yFrom;
let steps = params.frames;
let progress = params.frame;
return distance / steps * progress;
}
This will help us update the position values as the image gets animated. Then we’ll keep re-rendering the canvas until the animation is complete. We do this by adding the following code to our addImage() method.
Now we have animation! We’re steadily incrementing by 1 unit each time, which we call a linear animation.
CodePen Embed Fallback
You can see how the shape moves from point A to point B in a linear fashion, maintaining the same consistent speed between points. It’s functional, but lacks realism. The start and stop is jarring.
What we want is for the object to accelerate (ease-in) and decelerate (ease-out), so it mimics what a real-world object would do when things like friction and gravity come into play.
A JavaScript easing function
We’ll achieve this with a “cubic” ease-in and ease-out transition. We’ve modified one of the equations found in Robert Penner’s Flash easing functions, to be suitable for what we want to do here.
Inserting this into our code, which is a cubic ease, we get a much smoother result. Notice how the card speeds towards the center of the space, then slows down as it reaches the end.
CodePen Embed Fallback
Advanced easing with JavaScript
We can get a slower acceleration with either a quadratic or sinusoidal ease.
Rolling your own easing functions can be fun, but what if you want more power and flexibility? You could continue writing custom code, or you could consider a more powerful library. Let’s turn to the GreenSock Animation Platform (GSAP) for that.
Animation becomes a lot easier to implement with GSAP. Take this example, where the card bounces at the end. Note that the GSAP library is included in the demo.
The gsap.to method is where all the magic happens. During the two-second duration, the position object is updated and, with every update, onUpdate is called triggering the canvas to be redrawn.
Still unsure about which animation style and method you should be using in canvas when it comes to easing? Here’s a Pen showing different easing animations, including what’s offered in GSAP.
CodePen Embed Fallback
Check out my Solitaire card game to see a live demo of the non-GSAP animations. In this case, I’ve added animations so that the cards in the game ease-out and ease-in when they move between piles.
In addition to creating motions, easing functions can be applied to any other attribute that has a from and to state, like changes in opacity, rotations, and scaling. I hope you’ll find many ways to use easing functions to make your application or game look smoother.
The <canvas> element in HTML and Canvas API in JavaScript combine to form one of the main raster graphics and animation possibilities on the web. A common canvas use-case is programmatically generating images for websites, particularly games. That’s exactly what I’ve done in a website I built for playing Solitaire. The cards, including all their movement, is all done in canvas.
In this article, let’s look specifically at animation in canvas and techniques to make them look smoother. We’ll look specifically at easing transitions — like “ease-in” and “ease-out” — that do not come for free in canvas like they do in CSS.
Let’s start with a static canvas. I’ve drawn to the canvas a single playing card that I grabbed out of the DOM:
CodePen Embed Fallback
Let’s start with a basic animation: moving that playing card on the canvas. Even for fairly basic things like requires working from scratch in canvas, so we’ll have to start building out functions we can use.
First, we’ll create functions to help calculate X and Y coordinates:
function getX(params) {
let distance = params.xTo - params.xFrom;
let steps = params.frames;
let progress = params.frame;
return distance / steps * progress;
}
function getY(params) {
let distance = params.yTo - params.yFrom;
let steps = params.frames;
let progress = params.frame;
return distance / steps * progress;
}
This will help us update the position values as the image gets animated. Then we’ll keep re-rendering the canvas until the animation is complete. We do this by adding the following code to our addImage() method.
Now we have animation! We’re steadily incrementing by 1 unit each time, which we call a linear animation.
CodePen Embed Fallback
You can see how the shape moves from point A to point B in a linear fashion, maintaining the same consistent speed between points. It’s functional, but lacks realism. The start and stop is jarring.
What we want is for the object to accelerate (ease-in) and decelerate (ease-out), so it mimics what a real-world object would do when things like friction and gravity come into play.
A JavaScript easing function
We’ll achieve this with a “cubic” ease-in and ease-out transition. We’ve modified one of the equations found in Robert Penner’s Flash easing functions, to be suitable for what we want to do here.
Inserting this into our code, which is a cubic ease, we get a much smoother result. Notice how the card speeds towards the center of the space, then slows down as it reaches the end.
CodePen Embed Fallback
Advanced easing with JavaScript
We can get a slower acceleration with either a quadratic or sinusoidal ease.
Rolling your own easing functions can be fun, but what if you want more power and flexibility? You could continue writing custom code, or you could consider a more powerful library. Let’s turn to the GreenSock Animation Platform (GSAP) for that.
Animation becomes a lot easier to implement with GSAP. Take this example, where the card bounces at the end. Note that the GSAP library is included in the demo.
The gsap.to method is where all the magic happens. During the two-second duration, the position object is updated and, with every update, onUpdate is called triggering the canvas to be redrawn.
Still unsure about which animation style and method you should be using in canvas when it comes to easing? Here’s a Pen showing different easing animations, including what’s offered in GSAP.
CodePen Embed Fallback
Check out my Solitaire card game to see a live demo of the non-GSAP animations. In this case, I’ve added animations so that the cards in the game ease-out and ease-in when they move between piles.
In addition to creating motions, easing functions can be applied to any other attribute that has a from and to state, like changes in opacity, rotations, and scaling. I hope you’ll find many ways to use easing functions to make your application or game look smoother.
I’d say 85% of my grid usage is in one of these two categories…
I just need some pretty basic (probably equal width) columns that ends up being something like like grid-template-columns: repeat(3, minmax(0, 1fr));to be safe.
Actually doing some real layout where five minutes in I realize I’d really like subgrid.
Subgrid? It’s a nice intuitive way to have a child element on the grid inherit relevant grid lines from the parent grid.
Here’s a great recent video from Rachel Andrew covering it. Last year, we linked up her talk on the same! It’s such a clutch feature and I wish we could rely on it cross-browser. Right now, Firefox is the only one that has it. (Chrome issue, Safari issue)
In my recent video, right about at 20 minutes, I realize subgrid would make even a fairly simple layout much nicer, like removing the need for variables or resorting to magic numbers.
The question of how and where to learn HTML & CSS is a highly reasonable thing to ask. The answer depends on all sorts of things: how serious you are, your current foundation, what other resources are available to you, what you hope to do with what you learn, and how much time you have, among probably a zillion other things.
Let’s look at a bunch of options and you can choose the ones that feel right to you.
You could read a book.
There are a ton of books out there that cover HTML and CSS (and often together). They probably all do a fine job. There’s no need to chronicle all the choices here. These two are my personal recommendations. You probably don’t even need both.
Frontend Masters has a very in-depth bootcamp they give away for free. It’s 21 hours of high-quality video learning! If it clicks with you, you can sign up for the more advanced paid courses.
freeCodeCamp
freeCodeCamp is also (wait for it) free and has a step-by-step process to it where you don’t just watch, there are tasks for you to complete.
Khan Academy
Khan Academy has an Intro to HTML/CSS: Making webpages course that’s packaged in a super cool format. It’s like video in that you get to hear the instructor talk you through the learning, but what you see is a real live text editor and real-live output. Sometimes the teacher is controlling the code, and then sometimes it breaks for challenges in which you take over and edit the code yourself.
Don’t Fear the Internet
Jessica Hische and Russ Maschmeyer’s Don’t Fear the Internet is an eight-part series that gets you going with HTML & CSS — it even delves into the all-important topic of typography.
Through short tutorial videos, you’ll learn how to take a basic WordPress blog and manipulate the CSS, HTML (and even some PHP!) to match your aesthetic.
We designed HTML & CSS Is Hard to be the only introduction to HTML and CSS that you’ll ever need. If you put in the effort to read every section and write every code snippet, this tutorial has the potential to replace hundreds or even thousand of dollars worth of online courses and live training.
Scrimba / Intro to HTML
Eric Tirado has an Intro to HTML course on Scrimba, which is also a neat platform in that Eric’s voice guides you through the course, but visually it’s a combination of slides with a real code editor and preview.
You could read through all the posts in our Beginner’s Guide.
We have a guide (a collection of articles, videos, and links) called Just Starting Out with CSS & HTML. I hope there is stuff in there that can help kickstart or augment your early learning because that’s the intent.
You could find and take a paid online course.
I often join gyms because the accountability of paying for something gets me to do it. I know I can do situps, pushups, and go for a jog for free, but the gym membership makes a thing of it. Well, same could be said about paying for a course on HTML and CSS.
These are broad generalizations, but good places to start:
If you wanna put even more skin in the game, you could consider literally going to school. If you don’t have a college degree, that’s an option, although you’ll be looking at a broad education rather than a ticket to leveling up your web design and development skills alone. I’m a fan of that just for the general mind-broadening it involves.
But assuming you’re going to go to a coding-specific school…
There are options that exist in single cities. I know someone who went to the All-Woman’s coding bootcamp Hackbright in San Francisco. There are places like Actualize in Chicago, Center Centre in Tennessee, and HackerYou in Toronto.
There are bigger outfits like, Flatiron school (with campuses all around the U.S.) and General Assembly (with campuses all around the world).
There are probably dozens — if not hundreds — more, so this is more to inform you of the possibility of schooling. You don’t even have to go to a physical school since plenty of these offer online courses, too (but with the advantage of live instruction and cohorts). For example, LambdaSchool has the novelty of being free to start and paid later in the form of letting them take a portion of your salary after you get a job in the industry.
You could practice on CodePen.
Not every second of your learning should be strictly following some course laid out by a book, class, or teacher. It wouldn’t even be that way if you tried. You might as well embrace that. If something tickles your muse, go play!
I hope CodePen is a rewarding place to do that, making it both easy and useful, while providing a place to connect with other folks in the field.
You could build a personal site and learn what you need to get it done.
That’s how absolutely countless developers have cut their teeth, including me. I wanted a personal website years ago, and I struggled through getting a self-hosted WordPress site online so I could have full control over everything and bend it to my will. Once you have an actual website online, and you know at least some people are seeing it, it gives you all the motivation in the world to keep going and evolve further.
Equally as common: build a website for your band. Or a friend, friend-of-a-friend, or the business of your mother’s business partner’s sister. When you have a real project (a real website on the live internet) you have that feet-in-the-fire feeling that you’re responsible for something real that real people are going to see and you have to get it done and do a good job. That works tremendously well for some people.
You will actually learn by doing a combination of all this stuff.
People are obsessed with asking musicians if they’re “self-taught”. Like, if they are, their amazingness triples because it means their creative genius was delivered by a lightning bolt at birth. They don’t need anyone else to learn; they merely look at those guitar strings or piano keys and know what to do.
And if they were taught by a teacher, then, well, that’s all out the door. If they are good at all, then it’s because the teacher delivered that to them.
Total nonsense.
People learn anything — music and web development included — inside a hurricane of influences. Let’s stick with music for a second. Learning to play comes in many forms. You learn by listening to music an awful lot. You can do fundamental practice, like finger exercises and going up and down scales. You can learn to transpose chords on a chalkboard. You can watch YouTube all day and night. You can sign up for online courses. You can go to local jams to watch and play along. You can join a band. You can take lessons from someone advertising on Craigslist. You can go to a local music school. You can read books about music.
You get the idea.
You can and will do all of that. With learning web design and development, getting anywhere will involve all sorts of ways. There’s no silver bullet. It takes bashing on it lots of different ways. There’s no requirement to sprinkle money on it, but you do need multiple angles, time, and motivation.