To celebrate the 40th anniversary of the McDonald’s Happy Meal, we captured emotional relationship between the iconic Happy Meal and kids. As we know, kids have so much energy that make them never get tired to move so much. But it’s the bright red box with its golden handles that always manages to draw their attention, making them stop moving. Focus only on the red box of Happy Meal, enjoy the delicious meals inside and forget anything else.
You are probably already familiar
with the concept of call to action, but if somehow you are new to web
design, call to action refers to elements in a page that request an action from
its visitors.
If you are indeed new to web design,
there are high chances that you will neglect this important part of a website,
but the real problem is that experienced designers do it as well.
A lot of web designers struggle to
understand their true function, beyond looking attractive. Yet, call to action
buttons are too valuable to be placed carelessly on a website, without any real
regard for their purpose.
It is essential for designers and
developers to have a good understanding of the various ways in which color,
size, text, and other features can affect the value of a call to action button.
The techniques employed to create
better call to action buttons are not overly intricate, but they do need a
reasonable amount of planning and care if they are going to successfully
encourage visitors to exhibit desired behaviors.
For call to action buttons that
perform successfully, it is first necessary to work out how they should gel
with the rest of the website design. This is referred to as ‘establishing the
ground architecture’ and it will help you to further understand how call to
action buttons work within the web interface.
The primary goal of all business
websites is to turn a profit. As better call to action buttons actively
contribute to the achievement of this objective, it makes sense to spend a
reasonable amount of time thinking about their design, even if they do only
take up a tiny amount of space. In many ways, they are the true stars of a web
page.
How to make them better
Use size and color properly
It is a good idea to think carefully
about the size of your call to action buttons. A button that is too big is
likely to distract visitors in a negative way, but a button that is too small
will get lost in all of the other features which are competing for attention.
In fact, color is a great way to
further balance out the scale of the call to action buttons. For bigger
buttons, opt for a shade that is used infrequently within the overall website
design.
It should still be a color that is
bright enough to stand out. The opposite is true for shades that are used
frequently; in this case, a bold tone will really make the button stand out.
So, if you’re using a WordPress plugin to insert the buttons on the page, make sure not to use
the default ones. Customize them to your design and for your users. Use a
legible font, and make sure not to use one that you fancy from other sites.
This means that you should say no to using the font that Instagram uses just because you like it. Your
audience might not.
Use directional cues
It is common for businesses to
surround call to action buttons with images associated with clicking or looking
at them. This is to further encourage visitors to want to go where they promise
to lead.
If you use the right images, this
kind of technique can be very effective – why not try a series of arrows or
even a picture of a person looking directly at the button?
For human beings, directional
prompts can be very powerful. You only have to think about what happens when we
spot an individual looking intensely in a specific direction – in most cases,
everybody else would look there too, in order to find out what was causing such
interest. This is why directional cuing can be a successful technique.
The
copy featured in your call to action buttons needs to be simple and easy to understand. A good call to
action button is one that tells a visitor what it offers in a fraction of a
second. This means that they do not have to pause to find out, and are much
more likely to follow it.
It is perfectly okay, necessary in
fact, to use direct language within call to action buttons. For example, words
like Click Here, Call, Visit, Buy, Register, and Subscribe are common and
effective. Look at German startups and how they are doing things. They’re known for being
direct. Their call to action buttons have a simple and efficient copy.
However, if you want to have a unique website not just in terms of design, but
also copy, you can use more creative copy variations.
It is just as important to think
about the size of your copy. It should be significantly bigger than the rest of
the text on your website so that it stands out. It should also be boldly
colored, and contrast enough so that it is easy to read quickly.
If necessary, you can use a call to
action button to tell visitors what to expect. However, this is most effective
when it comes to the use of ‘trial’ and ‘download’ functions. The information
provided usually pertains to the size of a download, or the length of a free
trial.
For call to action buttons that
feature extra data, it is still vital that their key goal is prioritized above
all else.
In other words, do not forget the
action which you are trying to promote. This can be achieved by making sure
that the ‘action’ words are more prominent than everything else.
For most webpages, the best place to
position a call to action button is just above the fold. In fact, if a button
can only be reached with scrolling, many visitors will simply ignore it, or not
see it at all. This is what some people say, at least. The truth, however, is
that it depends.
You can get around this by placing
two of the same call to action buttons on a page, with one at the top and one
at the bottom. This way, if they can only be reached via scrolling, you have
doubled the chance that the prompt will be effective.
It is equally important to think
about proximity to other items. For instance, it can be valuable to position
call to action buttons close to reviews, testimonials, about us pages, and
anything else which clearly states what your company does, and what it promises
to offer visitors.
Use whitespace
It is a mistake to assume that the
placement of a call to action button is all that matters. The area surrounding
it can be just as vital because the more empty space there is around a call to
action button, the more chance there is of the eye being drawn there. If there
is too much ‘noise,’ they may get lost.
The main aim is to prompt visitors
to exhibit the behaviors which you want to see with as little effort as
possible.
Whilst deception is not the aim, it
is important to make sure that they do not get too many opportunities to pause
and think about whether or not to click through. The internet is a place that
moves extremely fast, and you have to work fast if you want to secure
conversions.
This is why it is important for call
to action buttons to convey a sense of urgency. They should make it seem like
the only opportunity is right now as if the only chance to take advantage is to
follow the directions quickly.
In the case of high-cost purchases,
this might not be successful, but for low ticket items, it can lead to a hike
in sales. For example, if your
site sells tickets to events, you might want to create a sense of urgency to sell them
faster.
Ending thoughts
In many different ways, call to
action buttons are essential to the success of online businesses. For all
website developers, the primary aim is to secure either more attention or
increased sales, and this feature is a big part of achieving that.
It could be purchases,
registrations, membership enrollment, or anything else which needs
participation – whatever the aim, use call to action buttons to make it so.
They may take up a tiny amount of space, but these little buttons can have a
big impact on business.
You are probably already familiar
with the concept of call to action, but if somehow you are new to web
design, call to action refers to elements in a page that request an action from
its visitors.
If you are indeed new to web design,
there are high chances that you will neglect this important part of a website,
but the real problem is that experienced designers do it as well.
A lot of web designers struggle to
understand their true function, beyond looking attractive. Yet, call to action
buttons are too valuable to be placed carelessly on a website, without any real
regard for their purpose.
It is essential for designers and
developers to have a good understanding of the various ways in which color,
size, text, and other features can affect the value of a call to action button.
The techniques employed to create
better call to action buttons are not overly intricate, but they do need a
reasonable amount of planning and care if they are going to successfully
encourage visitors to exhibit desired behaviors.
For call to action buttons that
perform successfully, it is first necessary to work out how they should gel
with the rest of the website design. This is referred to as ‘establishing the
ground architecture’ and it will help you to further understand how call to
action buttons work within the web interface.
The primary goal of all business
websites is to turn a profit. As better call to action buttons actively
contribute to the achievement of this objective, it makes sense to spend a
reasonable amount of time thinking about their design, even if they do only
take up a tiny amount of space. In many ways, they are the true stars of a web
page.
How to make them better
Use size and color properly
It is a good idea to think carefully
about the size of your call to action buttons. A button that is too big is
likely to distract visitors in a negative way, but a button that is too small
will get lost in all of the other features which are competing for attention.
In fact, color is a great way to
further balance out the scale of the call to action buttons. For bigger
buttons, opt for a shade that is used infrequently within the overall website
design.
It should still be a color that is
bright enough to stand out. The opposite is true for shades that are used
frequently; in this case, a bold tone will really make the button stand out.
So, if you’re using a WordPress plugin to insert the buttons on the page, make sure not to use
the default ones. Customize them to your design and for your users. Use a
legible font, and make sure not to use one that you fancy from other sites.
This means that you should say no to using the font that Instagram uses just because you like it. Your
audience might not.
Use directional cues
It is common for businesses to
surround call to action buttons with images associated with clicking or looking
at them. This is to further encourage visitors to want to go where they promise
to lead.
If you use the right images, this
kind of technique can be very effective – why not try a series of arrows or
even a picture of a person looking directly at the button?
For human beings, directional
prompts can be very powerful. You only have to think about what happens when we
spot an individual looking intensely in a specific direction – in most cases,
everybody else would look there too, in order to find out what was causing such
interest. This is why directional cuing can be a successful technique.
The
copy featured in your call to action buttons needs to be simple and easy to understand. A good call to
action button is one that tells a visitor what it offers in a fraction of a
second. This means that they do not have to pause to find out, and are much
more likely to follow it.
It is perfectly okay, necessary in
fact, to use direct language within call to action buttons. For example, words
like Click Here, Call, Visit, Buy, Register, and Subscribe are common and
effective. Look at German startups and how they are doing things. They’re known for being
direct. Their call to action buttons have a simple and efficient copy.
However, if you want to have a unique website not just in terms of design, but
also copy, you can use more creative copy variations.
It is just as important to think
about the size of your copy. It should be significantly bigger than the rest of
the text on your website so that it stands out. It should also be boldly
colored, and contrast enough so that it is easy to read quickly.
If necessary, you can use a call to
action button to tell visitors what to expect. However, this is most effective
when it comes to the use of ‘trial’ and ‘download’ functions. The information
provided usually pertains to the size of a download, or the length of a free
trial.
For call to action buttons that
feature extra data, it is still vital that their key goal is prioritized above
all else.
In other words, do not forget the
action which you are trying to promote. This can be achieved by making sure
that the ‘action’ words are more prominent than everything else.
For most webpages, the best place to
position a call to action button is just above the fold. In fact, if a button
can only be reached with scrolling, many visitors will simply ignore it, or not
see it at all. This is what some people say, at least. The truth, however, is
that it depends.
You can get around this by placing
two of the same call to action buttons on a page, with one at the top and one
at the bottom. This way, if they can only be reached via scrolling, you have
doubled the chance that the prompt will be effective.
It is equally important to think
about proximity to other items. For instance, it can be valuable to position
call to action buttons close to reviews, testimonials, about us pages, and
anything else which clearly states what your company does, and what it promises
to offer visitors.
Use whitespace
It is a mistake to assume that the
placement of a call to action button is all that matters. The area surrounding
it can be just as vital because the more empty space there is around a call to
action button, the more chance there is of the eye being drawn there. If there
is too much ‘noise,’ they may get lost.
The main aim is to prompt visitors
to exhibit the behaviors which you want to see with as little effort as
possible.
Whilst deception is not the aim, it
is important to make sure that they do not get too many opportunities to pause
and think about whether or not to click through. The internet is a place that
moves extremely fast, and you have to work fast if you want to secure
conversions.
This is why it is important for call
to action buttons to convey a sense of urgency. They should make it seem like
the only opportunity is right now as if the only chance to take advantage is to
follow the directions quickly.
In the case of high-cost purchases,
this might not be successful, but for low ticket items, it can lead to a hike
in sales. For example, if your
site sells tickets to events, you might want to create a sense of urgency to sell them
faster.
Ending thoughts
In many different ways, call to
action buttons are essential to the success of online businesses. For all
website developers, the primary aim is to secure either more attention or
increased sales, and this feature is a big part of achieving that.
It could be purchases,
registrations, membership enrollment, or anything else which needs
participation – whatever the aim, use call to action buttons to make it so.
They may take up a tiny amount of space, but these little buttons can have a
big impact on business.
[…] with WordPress child themes, you are all but guaranteed to get into the weeds of specificity, hunting around theme stylesheets that you didn’t author, trying to figure out what existing declaration is preventing you from applying a new style, and then figuring out the least specificity you need to override it, and then thinking “Maybe it would be faster if I just wrote all of this myself”.
Her point wasn’t child themes (although I think that’s a perfect thing to point to as the way you work with them is all with overriding what is already there), but the expectation of knowledge:
[…] unless you are “a CSS person” this understanding of specificity and its impact on the future of the code-base is somewhat specialized knowledge. Should everyone who writes CSS be expected to understand these details? Maybe, but the more experienced I become in all kinds of development, I’m starting to think that’s an unrealistic expectation given how much other stuff we have to know as developers.
We all have a number of interests and passions. For example, I’m interested in JavaScript, 90’s indie rock and hip hop, obscure jazz, the city of Pittsburgh, pizza, coffee, and movies starring John Lurie. We also have family members, friends, acquaintances, classmates, and colleagues who also have their own social relationships, interests, and passions. Some of these relationships and interests overlap, like my friend Riley who shares my interest in 90’s hip hop and pizza. Others do not, like my colleague Harrison, who prefers Python to JavaScript, only drinks tea, and prefers current pop music. All together, we each have a connected graph of the people in our lives, and the ways that our relationships and interests overlap.
These types of interconnected data are exactly the challenge that GraphQL initially set out to solve in API development. By writing a GraphQL API we are able to efficiently connect data, which reduces the complexity and number of requests, while allowing us to serve the client precisely the data that it needs. (If you’re into more GraphQL metaphors, check out Meeting GraphQL at a Cocktail Mixer.)
In this article, we’ll build a GraphQL API in Node.js, using the Apollo Server package. To do so, we’ll explore fundamental GraphQL topics, write a GraphQL schema, develop code to resolve our schema functions, and access our API using the GraphQL Playground user interface.
What is GraphQL?
GraphQL is an open source query and data manipulation language for APIs. It was developed with the goal of providing single endpoints for data, allowing applications to request exactly the data that is needed. This has the benefit of not only simplifying our UI code, but also improving performance by limiting the amount of data that needs to be sent over the wire.
What we’re building
To follow along with this tutorial, you’ll need Node v8.x or later and some familiarity with working with the command line.
We’re going to build an API application for book highlights, allowing us to store memorable passages from the things that we read. Users of the API will be able to perform “CRUD” (create, read, update, delete) operations against their highlights:
Create a new highlight
Read an individual highlight as well as a list of highlights
Update a highlight’s content
Delete a highlight
Getting started
To get started, first create a new directory for our project, initialize a new node project, and install the dependencies that we’ll need:
# make the new directory
mkdir highlights-api
# change into the directory
cd highlights-api
# initiate a new node project
npm init -y
# install the project dependencies
npm install apollo-server graphql
# install the development dependencies
npm install nodemon --save-dev
Before moving on, let’s break down our dependencies:
apollo-server is a library that enables us to work with GraphQL within our Node application. We’ll be using it as a standalone library, but the team at Apollo has also created middleware for working with existing Node web applications in Express, hapi, Fastify, and Koa.
graphql includes the GraphQL language and is a required peer dependency of apollo-server.
nodemon is a helpful library that will watch our project for changes and automatically restart our server.
With our packages installed, let’s next create our application’s root file, named index.js. For now, we’ll console.log() a message in this file:
console.log("📚 Hello Highlights");
To make our development process simpler, we’ll update the scripts object within our package.json file to make use of the nodemon package:
"scripts": {
"start": "nodemon index.js"
},
Now, we can start our application by typing npm start in the terminal application. If everything is working properly, you will see 📚 Hello Highlights logged to your terminal.
GraphQL schema types
A schema is a written representation of our data and interactions. By requiring a schema, GraphQL enforces a strict plan for our API. This is because the API can only return data and perform interactions that are defined within the schema. The fundamental component of GraphQL schemas are object types. GraphQL contains five built-in types:
String: A string with UTF-8 character encoding
Boolean: A true or false value
Int: A 32-bit integer
Float: A floating-point value
ID: A unique identifier
We can construct a schema for an API with these basic components. In a file named schema.js, we can import the gql library and prepare the file for our schema syntax:
const { gql } = require('apollo-server');
const typeDefs = gql`
# The schema will go here
`;
module.exports = typeDefs;
To write our schema, we first define the type. Let’s consider how we might define a schema for our highlights application. To begin, we would create a new type with a name of Highlight:
const typeDefs = gql`
type Highlight {
}
`;
Each highlight will have a unique ID, some content, a title, and an author. The Highlight schema will look something like this:
const typeDefs = gql`
type Highlight {
id: ID
content: String
title: String
author: String
}
`;
We can make some of these fields required by adding an exclamation point:
Though we’ve defined an object type for our highlights, we also need to provide a description of how a client will fetch that data. This is called a query. We’ll dive more into queries shortly, but for now let’s describe in our schema the ways in which someone will retrieve highlights. When requesting all of our highlights, the data will be returned as an array (represented as [Highlight]) and when we want to retrieve a single highlight we will need to pass an ID as a parameter.
Now, in the index.js file, we can import our type definitions and set up Apollo Server:
const {ApolloServer } = require('apollo-server');
const typeDefs = require('./schema');
const server = new ApolloServer({ typeDefs });
server.listen().then(({ url }) => {
console.log(`📚 Highlights server ready at ${url}`);
});
If we’ve kept the node process running, the application will have automatically updated and relaunched, but if not, typing npm start from the project’s directory in the terminal window will start the server. If we look at the terminal, we should see that nodemon is watching our files and the server is running on a local port:
[nodemon] 2.0.2
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node index.js`
📚 Highlights server ready at http://localhost:4000/
Visiting the URL in the browser will launch the GraphQL Playground application, which provides a user interface for interacting with our API.
GraphQL Resolvers
Though we’ve developed our project with an initial schema and Apollo Server setup, we can’t yet interact with our API. To do so, we’ll introduce resolvers. Resolvers perform exactly the action their name implies; they resolve the data that the API user has requested. We will write these resolvers by first defining them in our schema and then implementing the logic within our JavaScript code. Our API will contain two types of resolvers: queries and mutations.
Let’s first add some data to interact with. In an application, this would typically be data that we’re retrieving and writing to from a database, but for our example let’s use an array of objects. In the index.js file add the following:
let highlights = [
{
id: '1',
content: 'One day I will find the right words, and they will be simple.',
title: 'Dharma Bums',
author: 'Jack Kerouac'
},
{
id: '2',
content: 'In the limits of a situation there is humor, there is grace, and everything else.',
title: 'Arbitrary Stupid Goal',
author: 'Tamara Shopsin'
}
]
Queries
A query requests specific data from an API, in its desired format. The query will then return an object, containing the data that the API user has requested. A query never modifies the data; it only accesses it. We’ve already written a two queries in our schema. The first returns an array of highlights and the second returns a specific highlight. The next step is to write the resolvers that will return the data.
In the index.js file, we can add a resolvers object, which can contain our queries:
The highlights query returns the full array of highlights data. The highlight query accepts two parameters: parent and args. The parent is the first parameter of any GraqhQL query in Apollo Server and provides a way of accessing the context of the query. The args parameter allows us to access the user provided arguments. In this case, users of the API will be supplying an id argument to access a specific highlight.
We can then update our Apollo Server configuration to include the resolvers:
const server = new ApolloServer({ typeDefs, resolvers });
With our query resolvers written and Apollo Server updated, we can now query API using the GraphQL Playground. To access the GraphQL Playground, visit http://localhost:4000 in your web browser.
A query is formatted as so:
query {
queryName {
field
field
}
}
With this in mind, we can write a query that requests the ID, content, title, and author for each our highlights:
query {
highlights {
id
content
title
author
}
}
Let’s say that we had a page in our UI that lists only the titles and authors of our highlighted texts. We wouldn’t need to retrieve the content for each of those highlights. Instead, we could write a query that only requests the data that we need:
query {
highlights {
title
author
}
}
We’ve also written a resolver to query for an individual note by including an ID parameter with our query. We can do so as follows:
query {
highlight(id: "1") {
content
}
}
Mutations
We use a mutation when we want to modify the data in our API. In our highlight example, we will want to write a mutation to create a new highlight, one to update an existing highlight, and a third to delete a highlight. Similar to a query, a mutation is also expected to return a result in the form of an object, typically the end result of the performed action.
The first step to updating anything in GraphQL is to write the schema. We can include mutations in our schema, by adding a mutation type to our schema.js file:
Our newHighlight mutation will take the required value of content along with optional title and author values and return a Highlight. The updateHighlight mutation will require that a highlight id and content be passed as argument values and will return the updated Highlight. Finally, the deleteHighlight mutation will accept an ID argument, and will return the deleted Highlight.
With the schema updated to include mutations, we can now update the resolvers in our index.js file to perform these actions. Each mutation will update our highlights array of data.
With these mutations written, we can use the GraphQL Playground to practice mutating the data. The structure of a mutation is nearly identical to that of a query, specifying the name of the mutation, passing the argument values, and requesting specific data in return. Let’s start by adding a new highlight:
mutation {
newHighlight(author: "Adam Scott" title: "JS Everywhere" content: "GraphQL is awesome") {
id
author
title
content
}
}
We can then write mutations to update a highlight:
mutation {
updateHighlight(id: "3" content: "GraphQL is rad") {
id
content
}
}
And to delete a highlight:
mutation {
deleteHighlight(id: "3") {
id
}
}
Wrapping up
Congratulations! You’ve now successfully built a GraphQL API, using Apollo Server, and can run GraphQL queries and mutations against an in-memory data object. We’ve established a solid foundation for exploring the world of GraphQL API development.
In this post, Sarah Chima walks us through how we can work with browser events, such as clicking, using JavaScript. There’s a ton of great info in here! If JavaScript isn’t your strong suit, I think this is the best explanation of event handling that I’ve read in quite some time.
When an event occurs, the browser creates an event object and passes it as an argument to the event handler. This event object contains details of the event. For instance, you might want to know which button was clicked or which key was pressed or the mouse coordinates when the event occurred. You can get all of these from the event object.
Sarah also links to this really good primer on bubbling and capturing that’s worth checking out, too.
The Uncensored Library – The digital home of press freedom. Reporters Without Borders (RSF) opens “The Uncensored Library” – Within a computer game. In many countries, free information is hard to access. Blogs, newspapers and websites are censored but Minecraft is still accessible. RSF used this backdoor to build “The Uncensored Library”. A library filled with books, containing articles that were censored in their country of origin. These articles are now available again for young people around the world – hidden from government surveillance technology inside a computer game. Visit the uncensored library: uncensoredlibrary.com
We use the six numbers of the geolocation coordinates in Google Earth, to invite people to discover the incredible places that 6 numbers could take them, the same numbers of our ballots.
More and more people are considering going electric with their next car purchase. Whilst some people might not be ready to make the leap to full electric, BMW offers a range of Plug-in Hybrid (PHEV) cars, which combine a combustion petrol engine and an electric motor to offer the driver the benefit of both petrol and electric.
BMW Plug-in Hybrids (PHEV) are available on many of existing models in the range, from a saloon to an SUV. A PHEV is every inch a BMW, so they look, feel and drive exactly as you would expect the ultimate driving machine to.
This ground-breaking range of cars needed a show-stopping campaign. Creative agency FCB Inferno was briefed to create a campaign that clearly communicated how PHEVs offer the performance of petrol, with the efficiency of electric, in one BMW.
The campaign idea is strikingly simple. In the films, each time a BMW PHEV switches from petrol to electric, it glows with pure white light. When it changes back to petrol, the light disappears. In other words, the car is ‘Sometimes electric. Always BMW.’
Achieving this effect in a way that felt realistic was much harder than it looked, and the BMW PHEV shoot included a lot of firsts. A pioneering LED lighting rig was custom built specifically for the campaign, to give a real illumination effect rather than relying on special effects. An anamorphic camera normally used for IMAX movies gave a more cinematic feel. Add in flying drone shots through a working city, and a cameraman on rollerblades who used to skate at the X Games, and you get a sense of the level of craft that went into creating the campaign.
The result is an elegant visual metaphor that brings to life the PHEV range’s hidden yet innovative functionality. The film forms the first part of a wider programme that will be running throughout the year with the aim of helping consumers understand better the PHEV technology and the positive realities of living with it every day.
Brent Jackson says CSS utility libraries failed somewhat:
Eventually, you’ll need to add one-off styles that just aren’t covered by the library you’re using, and there isn’t always a clear way to extend what you’re working with. Without a clear way to handle things like this, developers tend to add inconsistent hacks and append-only styles.
I have a feeling Tailwind people would disagree. I have no particular opinion here, I’m just noting that Tailwind seems to have a more fervent fanbase than those early days of Basscss/Tachyons.
Brent goes on to say that CSS-in-JS solves the same problem, but in a better way:
CSS-in-JS libraries help solve a lot of the same issues Utility-based CSS methodologies were focused on (and more) in a much better way. They connect styles directly to elements without needing to name things or create abstractions in class selectors. They avoid append-only stylesheets with encapsulation and hashed classnames. These libraries work with existing build tools, allowing for code splitting, lazy loading, and dead code elimination with virtually zero effort, and they don’t require additional tools like Sass or PostCSS. Many libraries also include CSS performance optimizations, such as critical CSS, enabled by default so that developers don’t need additional tooling or even need to think about them.
No wonder people have been raving about this.
The one-step-back refers to the fact that CSS-in-JS is more open-ended and doesn’t encourage consistency as much. I’m not sure about that. Seems like if you’re building in a component-based way already, consistency kind of comes along for the ride, even before using design tokens and the like — which a CSS-in-JS approach also encourages.