That might look a little weird to us folks who are so used to the CSS syntax, where it is font-size (not fontSize), margin-bottom (not marginBottom), and semi-colons (not commas).
That’s not JSX (or React or whatever) being weird — that’s just how styles are in JavaScript. If you wanted to set the font-size from any other JavaScript, you’d have to do:
div.style.fontSize = "16px";
I say that, but other APIs do want you to use the CSS syntax, like:
There are also lots of CSS-in-JS libraries that either require or optionally support setting styles in this object format. I’ve even heard that with libraries that support both the CSS format (via template literals) and the object format (e.g. Emotion), that some people prefer the object syntax over the CSS syntax because it feels more at home in the surrounding JavaScript and is a bit less verbose when doing stuff like logic or injecting variables.
Anyway, the actual reason for the post is this little website I came across that converts the CSS format to the object format. CSS2JS:
Definitely handy if you had a big block of styles to convert.
[…] 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.
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.
You might reach for <input type="number> when you’re, you know, trying to collect a number in a form. But it’s got all sorts of issues. For one, sometimes what you want kinda looks like a number, but isn’t one (like how a credit card number has spaces), because it’s really just a string of numbers. Even more importantly, there are a variety of screen reader problems.
That last attribute is interesting and new to me. It means you get this super extra useful experience on browsers that support it:
There are other autocomplete values, as Phil writes:
There are many autocomplete values available, covering everything from names and addresses to credit cards and other account details. For sign up and login there are a few autocomplete values that stand out as useful hints: username, email, new-password, current-password.
Browsers and password managers have very good heuristics to find login forms on web pages, but using the username and current-password values make it very obvious.
Funny timing on this I was just looking at the website for Utopia (which is a responsive type project which I hate to admit I don’t fully understand) and I came across some CSS they show off that looked like this:
See anything weird there? That code is using mathematical operators, but there is no calc() function wrapped around it.
Just as my curiosity set in, Trys Mudford, a creator of Utopia, blogged it:
The value after the : in the CSS custom property does not have to be valid CSS. It won’t cause any errors, nor invalidate the custom property. It won’t be evaluated in the browser until used, or more specifically, placed in a calc() function.
Here’s a contrived example:
:root {
--padding: 1rem;
/* These are meaningless alone */
--padding-S: var(--padding) / 2;
--padding-L: var(--padding) * 2;
}
.module--large {
/* But they evaluate once they are in a calc() */
padding: calc(var(--padding-L));
}
In my limited understanding, currying is like functions that return functions. I suppose this is sorta like that in that the alternate padding properties above are sort of like derivative functions of the main padding function (if you can call it that), and you only call them and execute them as needed.
Have you ever clicked on an image on a webpage that opens up a larger version of the image with navigation to view other photos?
Some folks call it a pop-up. Others call it a lightbox. Bootstrap calls it a modal. I mention Bootstrap because I want to use it to make the same sort of thing. So, let’s call it a modal from here on out.
Why Bootstrap? you might ask. Well, a few reasons:
I’m already using Bootstrap on the site where I want this effect, so there’s no additional overhead in terms of loading resources.
I want something where I have complete and easy control over aesthetics. Bootstrap is a clean slate compared to most modal plugins I’ve come across.
The functionality I need is fairly simple. There isn’t much to be gained by coding everything from scratch. I consider the time I save using the Bootstrap framework to be more beneficial than any potential drawbacks.
Here’s where we’ll end up:
CodePen Embed Fallback
Let’s go through that, bit by bit.
Step 1: Create the image gallery grid
Let’s start with the markup for a grid layout of images. We can use Bootstrap’s grid system for that.
Now we need data attributes to make those images interactive. Bootstrap looks at data attributes to figure out which elements should be interactive and what they should do. In this case, we’ll be creating interactions that open the modal component and allow scrolling through the images using the carousel component.
About those data attributes:
We’ll add data-toggle="modal" and data-target="#exampleModal" to the parent element (#gallery). This makes it so clicking anything in the gallery opens the modal. We should also add the data-target value (#exampleModal) as the ID of the modal itself, but we’ll do that once we get to the modal markup.
Let’s add data-target="#carouselExample" and a data-slide-to attribute to each image. We could add those to the image wrappers instead, but we’ll go with the images in this post. Later on, we’ll want to use the data-target value (#carouselExample) as the ID for the carousel, so note that for when we get there. The values for data-slide-to are based on the order of the images.
This is a carousel inside a modal, both of which are standard Bootstrap components. We’re just nesting one inside the other here. Pretty much a straight copy-and-paste job from the Bootstrap documentation.
Here’s some important parts to watch for though:
The modal ID should match the data-target of the gallery element.
The carousel ID should match the data-target of the images in the gallery.
The carousel slides should match the gallery images and must be in the same order.
Here’s the markup for the modal with our attributes in place:
Looks like a lot of code, right? Again, it’s basically straight from the Bootstrap docs, only with our attributes and images.
Step 3: Deal with image sizes
This isn’t necessary, but if the images in the carousel have different dimensions, we can crop them with CSS to keep things consistent. Note that we’re using Sass here.
You may have noticed that the markup uses the same image files in the gallery as we do in the modal. That doesn’t need to be the case. In fact, it’s a better idea to use smaller, more performant versions of the images for the gallery. We’re going to be blowing up the images to their full size version anyway in the modal, so there’s no need to have the best quality up front.
The good thing about Bootstrap’s approach here is that we can use different images in the gallery than we do in the modal. They’re not mutually exclusive where they have to point to the same file.
So, for that, I’d suggest updating the gallery markup with lower-quality images:
<div class="row" id="gallery" data-toggle="modal" data-target="#exampleModal">
<div class="col-12 col-sm-6 col-lg-3">
<img class="w-100" src="/image-1-small.jpg" data-target="#carouselExample" data-slide-to="0">
<!-- and so on... -->
</div>
That’s it!
The site where I’m using this has already themed Bootstrap. That means everything is already styled to spec. That said, even if you haven’t themed Bootstrap you can still easily add custom styles! With this approach (Bootstrap vs. plugins), customization is painless because you have complete control over the markup and Bootstrap styling is relatively sparse.
Burke Holland thinks that to „build applications without thinking about servers” is a pretty good way to describe serverless, but…
Nobody really thinks about servers when they are writing their code. I mean, I doubt any developer has ever thrown up their hands and said “Whoa, whoa, whoa. Wait just a minute. We’re not declaring any variables in this joint until I know what server we’re going to be running this on.”
Instead of just one idea wrap it all up, Burke thinks there are three laws:
Law of Furthest Abstraction (I don’t really care where my code runs, just that it runs.)
The Law of Inherent Scale (I can hammer this code if I need to, or barely use it at all.)
Law of Least Consumption (I only pay for what I use.)
Not long ago, I posted about PHP templating in just PHP (which is basically HEREDOC syntax). I’m literally using that technique for some super basic templating I needed to do on this very WordPress site. The main pushback was that this kind of thing can be an XSS vulnerability. In my case, it’s not, because I’m not using it for anything other than an abstraction convenience for my own hand-written strings.
Since then, we’ve had a couple of good articles about templating and I’ve seen some other approaches. I thought I’d make a quick link dump of them.
Chris Geelhoed took a different approach than I did, passing data to a functio then using a require statement for a template file that expects global variables you set right before the require.
If you’re into the idea of using Twig as a PHP templating engine on your WordPress site, check out Timber. TJ Fogarty has written about this for us.
If Timber is a little heavy-handed, check out Sprig from Russell Heimlich. I really like this approach!