Snippets

Coding CSS for Context

Dave Rupert recently tweeted asking a question that I see quite often:

Code language: CSS

.some-context .thing { /* special rules and overrides */ } 

Does that go in thing.css or some-context.css?

Then, Harry Roberts discussed this concept further in his article of CSS Code Smells Revisited.

Harry uses a practical example of .thing being a .button. (Well, actually, a .btn but whatever. And yes, I just “well, actuallied” myself. It’s preemptive mansplaining.)

You’ll have the standard button that appears throughout your application. And then you have this variation in modal dialogs.

Instinctively, we start writing .modal .button. Hence, Dave’s question of where to put this particular bit of code. It’s interesting to note that the results of Dave’s survey indicated that a slim majority of people prefer that this bit of code live in with the modal CSS and not with the button CSS.

Harry indicated that it should live with the button CSS. And I agree with him. We’re styling a button! It should be in with the buttons.

[…]

One thing you have to worry about is components becoming too complex. Yes, the modal has a button. It could also have inputs and headings and all sorts of things. Over my career, I’ve noticed useful boundaries and tend not to create components with deep hierarchies.

Identifying The Thing

Going back to our thing that we’re trying to style: the button. Yes, right now, we’re styling a button in a modal dialog. Is this the only place that this exists? Right now, quite possibly. Will it always be the only place it exists? If your project is constantly in flux, then not likely.

Here’s what’s important:

  • We want to identify that this is a variation on our button.
  • We want to indicate the purpose of this button style.
  • We want to avoid tying the code to a particular context that could change.

Going with .button--modal, for example, now identifies it as a variation. But fails on the other two points: It indicates its context and doesn’t say what it’s trying to do other than be in a particular place on the page.

So, why is the button in the modal different than regular buttons? (If you’re the designer, ask yourself this. If you’re not the designer, ask them this.) You might get something like, “It needs to be green to draw attention to the fact that it’s a primary action.” Or maybe something like, “the button is smaller because we don’t have as much room.”

This helps you come up with a name like .button--primary or .button--compact.

Either of those names satisfy the three points I mentioned above.

  • It identifies itself as a variation using the BEM double hyphen.
  • It indicates its purpose through the variation name.
  • It hasn’t tied itself to a specific context.

That last point, to me, is the most important. As a designer, I might end up using these styles on a new page that hasn’t been thought up yet. I might want to use a primary button style on a form that isn’t in a modal dialog. I might want to use a compact button in a sidebar where I don’t have a lot of room.

And as Harry also mentioned, by keeping all our button styles in one place, we have the ability to see patterns emerge across an entire project.

Three months down the line, do we suddenly find ourselves with 30 button styles and need to reduce the complexity of our UI? That can be harder to do if button styles are strewn throughout the codebase, hidden within other contexts.

Typefaces: NPM packages for Open Source typefaces - making it easier to self-host webfonts

Why

  • Self-hosting is significantly faster. Loading a typeface from Google Fonts or other hosted font service adds an extra (blocking) network request. In my testing, I’ve found replacing Google Fonts with a self-hosted font can improve a site’s speedindex by ~300 miliseconds on desktop and 1+ seconds on 3g. This is a big deal.
  • Your fonts load offline. It’s annoying to start working on a web project on the train or airplane and see your interface screwed up because you can’t access Google fonts. I remember once being in this situation and doing everything possible to avoid reloading a project as I knew I’d lose the fonts and be forced to stop working.
  • Go beyond Google Fonts. Some of my favorite typefaces aren’t on Google Fonts like Clear Sans, Cooper Hewitt, and Aleo.
  • All web(site|app) dependencies should be managed through NPM whenever possible. Tis the modern way.

What

Each typeface package ships with all the necessary font files and css to self-host an open source typeface.

All Google Fonts have been added as well as a small but growing list of other open source fonts. Open an issue if you want a font added!

How

Couldn’t be easier. This is how you’d add Open Sans.

npm install --save typeface-open-sans

Then in your app or site’s entry file.

require("typeface-open-sans")

And that’s it! You’re now self-hosting Open Sans!

It should take < 5 minutes to swap out Google Fonts.

Typeface assumes you’re using webpack with loaders setup for loading css and font files (you can use Typeface with other setups but webpack makes things really really simple). Assuming your webpack configuration is setup correctly you then just need to require the typeface in the entry file for your project.

Many tools built with webpack such as Gatsby and Create React App are already setup to work with Typefaces. Gatsby by default also embeds your CSS in your <head> for even faster loading.

If you’re not using webpack or equivalent tool that allows you to require css, then you’ll need to manually integrate the index.css and font files from the package into your build system.

Duoload: Simplest website load comparison tool, ever

This is pretty excellent tool. (Note that it cannot be used on sites that disable iframe embedding, however.)

Today I needed a quick tool to compare the loading progression (not just loading time, but also incremental rendering) of two websites, one remote and one in my localhost. Just have them side by side and see how they load relative to each other. Maybe even record the result on video and study it afterwards. That’s all. No special features, no analysis, no stats.

read.isthe.link: A basic functionality Readability almost-clone

A basic functionality [Readability] almost-clone. This service will try to search for the body of the content to a URL, and represent it stripped back and with minimal styling.

Usage

Send your URL to https://read.isthe.link via a query string, and so long as the URL is publically available (i.e. not behind login), then the page can be re-rendered:

https://read.isthe.link?url=https://remysharp.com/node

The page will be cached for a period of time, so subsequent requests will be faster.

Usage with private URLs

You can POST a body to the service and it will give you a hashed URL to redirect to. For example:

Code language: JavaScript

const xhr = new XMLHttpRequest();
 
xhr.open('POST', 'https://read.isthe.link');
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('referrer', window.location);
 
xhr.onload = () => {
  const res = JSON.parse(xhr.response);
  window.location = `https://read.isthe.link?url=${res.url}`;
}
 
xhr.send(`body=${encodeURIComponent(document.documentElement.innerHTML)}`);

Issues & feedback

All feedback, suggestions, pull requests to github (please): https://github.com/remy/read-body

MIT Licensed

LayerSnap! Markup-based SVG Animations

Every so often we come across parts of our designs that could really benefit from a smooth build animation or transition. Fortunately, we use a lot of SVG for delivering our vector graphics, so we have a great deal of animation flexibility at our disposal, and one tool we’ve enjoyed using for helping us animate our SVGs is SnapSVG, by Adobe. Snap is great, but takes a decent amount of JavaScript skill and tinkering to churn out an animation.

While working on some projects last year, we realized that if we had a more user-friendly, markup-based approach to configuring our SVG animations, we’d be more productive, and our clients could easily work with their own animations after hand-off as well. So we built an open-source tool!

Introducing LayerSnap

LayerSnap is a script that builds on top of Snap SVG to build simple SVG animations by editing the SVG markup’s attributes. It comes with a suite of pre-set build transitions like “fade”, “move-down”, “enter-left”, “rotate-right”, etc. It also has an “anvil” transition, because no animation toolkit is complete without an anvil transition. These transitions can be configured via an attribute on every group (g) element in an SVG, and a special syntax allows you to combine each transition with a host of configuration settings for their speed, delay, easing, looping, repeating, and even interactivity.

Demos, Docs, and more

This is our initial release of LayerSnap, so we expect it’ll have some issues here and there to work out. We’d love your help in testing it out. LayerSnap has a couple of dependencies (a CSS file and Snap SVG’s JavaScript), but you’ll notice our project demos include jQuery and some other utilities for cueing animations when they enter the viewport as you scroll. jQuery isn’t required by LayerSnap, but if you’re already using it in your project, you’ll find a helper script or two in the LayerSnap repo makes it easier to auto-run your animations.