Developer News

Third-Party Components at Their Best

Css Tricks - Thu, 01/16/2020 - 11:49am

I'm a fan of the componentization of the web. I think it's a very nice way to build a website at just about any scale (except, perhaps, the absolute most basic). There are no shortage of opinions about what makes a good component, but say we scope that to third-party for a moment. That is, components that you just use, rather than components that you build yourself as part of your site's unique setup.

What makes a third-party component good? My favorite attribute of a third-party component is when it takes something hard and makes it easy. Particularly things that recognize and properly handle nuances, or things that you might not even know enough about to get right.

Perhaps you use some component that does pop-up contextual menus for you. It might perform browser edge detection, such as ensuring the menu never appears cut off or off-screen. That's a tricky little bit of programming that you might not get right if you did it yourself — or even forget to do.

I think of the <Link /> component that React Router has or what's used on Gatsby sites. It automatically injects aria-current="page" for you on the links when you're on that page. You can and probably should use that for a styling hook! And you probably would have forgotten to program that if you were handling your own links.

In that same vein, Reach UI Tabs have rigorous accessibility baked into them that you probably wouldn't get right if you hand-rolled them. This React image component does all sorts of stuff that is relatively difficult to pull off with images, like the complex responsive images syntax, lazy loading, placeholders, etc. This is, in a sense, handing you best practices for "free."

Here's a table library that doesn't even touch UI for you, and instead focuses on other needs you're likely to have with tables, which is another fascinating approach.

Anyway! Here's what y'all said when I was asking about this. What makes a third-party component awesome? What do the best of them do? (besides the obvious, like good docs and good accessibility)? Some of these might be at-odds. I'm just listing what people said they like.

  • Plug-and-play. It should "just work" with minimal config.
  • Lots of editable demos
  • Highly configurable
  • "White label" styling. Don't bring too strong of design choices.
  • Styled via regular CSS so you can BYO own styling tools
  • Fast
  • Small
  • Is installable via a package manager
  • Can be manually instantiated
  • Can be given a DOM node where it can go
  • Follows a useful versioning scheme
  • Is manintained, particularly for security
  • Has a public roadmap
  • Is framework-agnostic
  • Doesn't have other dependencies
  • Uses intuitive naming conventions
  • Supports internationalization
  • Has lots of tests

Anything you'd add to that list?

The post Third-Party Components at Their Best appeared first on CSS-Tricks.

NetNewsWire and Feedbin

Css Tricks - Thu, 01/16/2020 - 11:49am

NetNewsWire is one of the classic RSS apps, debuting in 2002. I was pretty stoked when it went 5.0 and was open-sourced in August 2019! You can snag it right here. (Sorry, Mac only.)

It's super nice, is fast, and looks great. It has just the right features.

But... I thought, at least at first, that really prefer websites for reading RSS content. I have multiple machines. I have mobile devices. I don't want my RSS to be limited to my laptop, I want an online service.

NetNewsWire on my Mac

Well! I found out that NetNewsWire syncs with my favorite website for RSS: Feedbin. The syncing works flawlessly. Both unread items and all the organization. In fact, the UI for organizing feeds is so nice in NetNewsWire that I managed everything there and was pleasantly surprised how it all synced perfectly with Feedbin.

Feedbin on the web

Who’s gonna read your personal blog because it has an RSS feed? I’m gonna read your personal blog because it has an RSS feed. pic.twitter.com/mtcyKhEVet

— Chris Coyier (@chriscoyier) January 7, 2020

I know a lot of people miss Google Reader, but I think we've arrived at an even better place after all these years. The Google Reader UI for Google Reader was OK, but the main benefit was that it was the central place where everything synced together. That meant people could experiment by building readers and could use whatever they wanted. Feedbin clearly has APIs that can handle those types of things, so perhaps it could become that central hub service, which would be awesome.

I use Reeder on iOS, which also syncs with Feedbin. The central hub is real.

Reeder on iOS

I know a lot of people love Feedly too, which is also good. I just click with Feedbin better. I particularly like the Feedbin feature where it gives me an email address I can have newsletters sent to, letting me subscribe to a ton of them the same way I do with sites.

The post NetNewsWire and Feedbin appeared first on CSS-Tricks.

Thinking Through Styling Options for Web Components

Css Tricks - Thu, 01/16/2020 - 6:02am

Where do you put styles in web components?

I'm assuming that we're using the Shadow DOM here as, to me, that's one of the big draws of a web component: a platform thing that is a uniquely powerful thing the platform can do. So this is about defining styles for a web component in a don't-leak-out way, and less so a way to get global styles to leak in (although that's very interesting as well, which can be done via custom properties which we'll look at later in the article).

If you're building the template inside the JavaScript — which is nice because of template literals and how we can sprinkle our data into the template nicely — you need access to those styles in JavaScript.

const template = ` <style>${styles}</style> <div class="${class}"> <h2>${title}</h2> ${content} </div> `;

Where does that style variable come from? Maybe also a template literal?

const style = ` :host { background: white; } h2 { font: 900 1.5rem/1.1 -system-ui, sans-serif; } `;

I guess that's fine, but it makes for a big messy block of code just dunked somewhere in the class where you're trying to build this web component.

Another way is to <template> the template and make a <style> block part of it.

<template id="card-template"> <style> :host { background: white; } h2 { font: 900 1.5rem/1.1 -system-ui, sans-serif; } </style> <div id="card-hook"> <h2 id="title-hook"></h2> <p id="desc-hook"></p> </div> </template>

I can see the appeal with this because it keeps HTML in HTML. What I don't love about it is that you have to do a bunch of manual shadowRoot.querySelector("#title-hook").innerHTML = myData.title; work in order to flesh out that template. That doesn't feel like a convenient template. I also don't love that you need to just chuck this template somewhere in your HTML. Where? I dunno. Just chuck it in there. Chuck it.

The CSS is moved out of the JavaScript too, but it just moved from one awkward location to another.

If we wanted to keep the CSS in a CSS file, we can sorta do that like this:

<template id="card-template"> <style> @import "/css/components/card.css"; </style> <div id="card-hook"> <h2 id="title-hook"></h2> <p id="desc-hook"></p> </div> </template>

(The use of <link rel="import" type="css" href=""> is deprecated, apparently.)

Now we have @import which is an extra HTTP Request, and notorious for being a performance hit. An article by Steven Lambert says it clocked in at half a second slower. Not ideal. I don't suppose it would be much better to do this instead:

class MyComponent extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); fetch('/css/components/card.css') .then(response => response.text()) .then(data => { let node = document.createElement('style'); node.innerHTML = data; document.body.appendChild(node); }); } // ... }

Seems like that would potentially be a Flash-of-Unstyled-Web-Component? I guess I should get off my butt and test it.

Now that I'm digging into this again, it seems like ::part has gotten some steam (explainer). So I can do...

const template = ` <div part="card"> <h2>${title}</h2> ${content} </div> `;

...then write styles in a global stylesheet that only apply inside that Shadow DOM, like:

my-card::part(card) { background: black; color: white; }

...which has a smidge of browser support, but maybe not enough?

These "part" selectors can only touch the exact element it's connected to. You'd have to do all your styling by applying a part name to every single DOM node and then styling each entirely on its own. That's no fun, particularly because the appeal of the Shadow DOM is this isolated styling environment in which we're supposed to be able to write looser CSS selectors and not be worried our h2 { } style is going to leak all over the place.

Looks like if native CSS modules becomes a thing, that will be the most helpful thing that could happen.

import styles from './styles.css'; class MyElement extends HTMLElement { constructor() { this.attachShadow({mode: open}); this.shadowRoot.adoptedStyleSheets = [styles]; } }

I'm not sure, however, if this is any sort of performance boost. Seems like it would be a wash between this and @import. I have to say I prefer the clarity and syntax with native CSS modules. It's nice to be writing JavaScript when working with JavaScript.

Constructable Stylesheets also look helpful for sharing a stylesheet across multiple components. But the CSS modules approach looks like it could also do that since the stylesheet has already become a variable at that point.

The post Thinking Through Styling Options for Web Components appeared first on CSS-Tricks.

The Design Squiggle

Css Tricks - Thu, 01/16/2020 - 6:02am

I think we all have an intuitive understanding that, at the beginning of projects that require our creativity (be it design or code), things feel uncertain and messy. Then, as we go, things tend to straighten out. There is still some wiggling and setbacks, but by the end, we find a single solution and ship it.

Apparently this feeling has a logo: The Design Squiggle

The Process of Design Squiggle by Damien Newman, thedesignsquiggle.com

It comes from Damien Newman who says that a client gave him 30 seconds to sell them on the value of design, and this did the trick.

I find it a little funny to take this little concept and give it such a grandiose presentation. A dedicated website! A story with a boatload of name dropping! Very specific attribution instructions! But hey, I don't have any famous doodles, and I gotta admit, this does a great job of expressing a complex thing quite quickly.

Reminds me of a boss a buddy of mine had who claims to have invented the Curiously Strong motto for Altoids, and didn't mind telling people about it.

Direct Link to ArticlePermalink

The post The Design Squiggle appeared first on CSS-Tricks.

How We Tagged Google Fonts and Created goofonts.com

Css Tricks - Wed, 01/15/2020 - 1:45pm

GooFonts is a side project signed by a developer-wife and a designer-husband, both of them big fans of typography. We’ve been tagging Google Fonts and built a website that makes searching through and finding the right font easier.

GooFonts uses WordPress in the back end and NuxtJS (a Vue.js framework) on the front end. I’d love to tell you the story behind goofonts.com and share a few technical details regarding the technologies we’ve chosen and how we adapted and used them for this project.

Why we built GooFonts

At the moment of writing this article, there are 977 typefaces offered by Google Fonts. You can check the exact number at any moment using the Google Fonts Developer API. You can retrieve the dynamic list of all fonts, including a list of the available styles and scripts for each family.

The Google Fonts website provides a beautiful interface where you can preview all fonts, sorting them by trending, popularity, date, or name. 

But what about the search functionality? 

You can include and exclude fonts by five categories: serif, sans-serif, display, handwriting, and monospace.

You can search within scripts (like Latin Extended, Cyrillic, or Devanagari (they are called subsets in Google Fonts). But you cannot search within multiple subsets at once.

You can search by four properties: thickness, slant, width, and "number of styles." A style, also called variant, refers both to the style (italic or regular) and weights (100, 200, up to 900). Often, the body font requires three variants: regular, bold, and italic. The “number of styles” property sorts out fonts with many variants, but it does not allow to select fonts that come in the “regular, bold, italic” combo.

There is also a custom search field where you can type your query. Unfortunately, the search is performed exclusively over the names of the fonts. Thus, the results often include font families uniquely from services other than Google Fonts. 

Let's take the "cartoon" query as an example. It results in "Cartoon Script" from an external foundry Linotype.

I can remember working on a project that demanded two highly stylized typefaces — one evoking the old Wild West, the other mimicking a screenplay. That was the moment when I decided to tag Google Fonts. :)

GooFonts in action

Let me show you how GooFonts works. The dark sidebar on the right is your  “search” area. You can type your keywords in the search field — this will perform an “AND” search. For example, you can look for fonts that are at once cartoon and slab. 

We handpicked a bunch of keywords — click any of them! If your project requires some specific subsets, check them in the subsets sections.  You can also check all the variants that you need for your font.

If you like a font, click its heart icon, and it will be stored in your browser’s localStorage. You can find your bookmarked fonts on the goofonts.com/bookmarks page. Together with the code, you might need to embed them.

How we built it: the WordPress part

To start, we needed some kind of interface where we could preview and tag each font. We also needed a database to store those tags. 

I had some experience with WordPress. Moreover, WordPress comes with its REST API,  which opens multiple possibilities for dealing with the data on the front end. That choice was made quickly.

I went for the most straightforward possible initial setup. Each font is a post, and we use post tags for keywords. A custom post type could have worked as well, but since we are using WordPress only for the data, the default content type works perfectly well.

Clearly, we needed to add all the fonts programmatically. We also needed to be able to programmatically update the fonts, including adding new ones or adding new available variants and subsets.

The approach described below can be useful with any other data available via an external API. In a custom WordPress plugin, we register a menu page from which we can check for updates from the API. For simplicity, the page will display a title, a button to activate the update and a progress bar for some visual feedback.

/** * Register a custom menu page. */ function register_custom_menu_page() { add_menu_page( 'Google Fonts to WordPress', 'WP GooFonts', 'manage_options', 'wp-goofonts-menu', function() { ?> <h1>Google Fonts API</h1> <button type="button" id="wp-goofonts-button">Run</button> <p id="info"></p> <progress id="progress" max="100" value="0"></progress> <?php } ); } add_action( 'admin_menu', 'register_custom_menu_page' );


Let's start by writing the JavaScript part. While most of the examples of using Ajax with WordPress implements jQuery and the jQuery.ajax method, the same can be obtained without jQuery, using axios and a small helper Qs.js for data serialization.

We want to load our custom script in the footer, after loading axios and qs:

add_action( 'admin_enqueue_scripts' function() { wp__script( 'axios', 'https://unpkg.com/axios/dist/axios.min.js' ); wp_enqueue_script( 'qs', 'https://unpkg.com/qs/dist/qs.js' ); wp_enqueue_script( 'wp-goofonts-admin-script', plugin_dir_url( __FILE__ ) . 'js/wp-goofonts.js', array( 'axios', 'qs' ), '1.0.0', true ); });

Let’s look how the JavaScript could look like:

const BUTTON = document.getElementById('wp-goofonts-button') const INFO = document.getElementById('info') const PROGRESS = document.getElementById('progress') const updater = { totalCount: 0, totalChecked: 0, updated: [], init: async function() { try { const allFonts = await axios.get('https://www.googleapis.com/webfonts/v1/webfonts?key=API_KEY&sort=date') this.totalCount = allFonts.data.items.length INFO.textContent = `Fetched ${this.totalCount} fonts.` this.updatePost(allFonts.data.items, 0) } catch (e) { console.error(e) } }, updatePost: async function(els, index) { if (index === this.totalCount) { return } const data = { action: 'goofonts_update_post', font: els[index], } try { const apiRequest = await axios.post(ajaxurl, Qs.stringify(data)) this.totalChecked++ PROGRESS.setAttribute('value', Math.round(100*this.totalChecked/this.totalCount)) this.updatePost(els, index+1) } catch (e) { console.error(e) } } } BUTTON.addEventListener('click', () => { updater.init() })

The init method makes a request to the Google Fonts API. Once the data from the API is available, we call the recursive asynchronous updatePost method that sends an individual font in the POST request to the WordPress server.

Now, it’s important to remember that WordPress implements Ajax in its specific way. First of all, each request must be sent to wp-admin/admin-ajax.php. This URL is available in the administration area as a global JavaScript variable ajaxurl.

Second, all WordPress Ajax requests must include an action argument in the data. The value of the action determines which hook tag will be used on the server-side.

In our case, the action value is goofonts_update_post. That means what happens on the server-side is determined by the wp_ajax_goofonts_update_post hook.

add_action( 'wp_ajax_goofonts_update_post', function() { if ( isset( $_POST['font'] ) ) { /* the post tile is the name of the font */ $title = wp_strip_all_tags( $_POST['font']['family'] ); $variants = $_POST['font']['variants']; $subsets = $_POST['font']['subsets']; $category = $_POST['font']['category']; /* check if the post already exists */ $object = get_page_by_title( $title, 'OBJECT', 'post' ); if ( NULL === $object ) { /* create a new post and set category, variants and subsets as tags */ goofonts_new_post( $title, $category, $variants, $subsets ); } else { /* check if $variants or $subsets changed */ goofonts_update_post( $object, $variants, $subsets ); } } }); function goofonts_new_post( $title, $category, $variants, $subsets ) { $post_id = wp_insert_post( array( 'post_author' => 1, 'post_name' => sanitize_title( $title ), 'post_title' => $title, 'post_type' => 'post', 'post_status' => 'draft', ) ); if ( $post_id > 0 ) { /* the easy part of tagging ;) append the font category, variants and subsets (these three come from the Google Fonts API) as tags */ wp_set_object_terms( $post_id, $category, 'post_tag', true ); wp_set_object_terms( $post_id, $variants, 'post_tag', true ); wp_set_object_terms( $post_id, $subsets, 'post_tag', true ); } }

This way, in less than a minute, we end up with almost one thousand post drafts in the dashboard — all of them with a few tags already in place. And that’s the moment when the crucial, most time-consuming part of the project begins. We need to start manually add tags for each font one by one.
The default WordPress editor does not make much sense in this case. What we needed is a preview of the font. A link to the font’s page on fonts.google.com also comes in handy.

custom meta box does the job very well. In most cases, you will use meta boxes for custom form elements to save some custom data related to the post. In fact, the content of a meta box can be practically any HTML.

function display_font_preview( $post ) { /* font name, for example Abril Fatface */ $font = $post->post_title; /* font as in url, for example Abril+Fatface */ $font_url_part = implode( '+', explode( ' ', $font )); ?> <div class="font-preview"> <link href="<?php echo 'https://fonts.googleapis.com/css?family=' . $font_url_part . '&display=swap'; ?>" rel="stylesheet"> <header> <h2><?php echo $font; ?></h2> <a href="<?php echo 'https://fonts.google.com/specimen/' . $font_url_part; ?>" target="_blank" rel="noopener">Specimen on Google Fonts</a> </header> <div contenteditable="true" style="font-family: <?php echo $font; ?>"> <p>The quick brown fox jumps over a lazy dog.</p> <p style="text-transform: uppercase;">The quick brown fox jumps over a lazy dog.</p> <p>1 2 3 4 5 6 7 8 9 0</p> <p>& ! ; ? {}[]</p> </div> </div> <?php } add_action( 'add_meta_boxes', function() { add_meta_box( 'font_preview', /* metabox id */ 'Font Preview', /* metabox title */ 'display_font_preview', /* content callback */ 'post' /* where to display */ ); });

Tagging fonts is a long-term task with a lot of repetition. It also requires a big dose of consistency. That’s why we started by defining a set of tag “presets.” That could be, for example:

{ /* ... */ comic: { tags: 'comic, casual, informal, cartoon' }, cursive: { tags: 'cursive, calligraphy, script, manuscript, signature' }, /* ... */ }

Next with some custom CSS and JavaScript, we “hacked” the WordPress editor and tags form by enriching it with the set of preset buttons. 

How we built it: The front end part (using NuxtJS)

The goofonts.com interface was designed by Sylvain Guizard, a french graphic and web designer (who also happens to be my husband). We wanted something simple with a distinguished “search” area. Sylvain deliberately went for colors that are not too far from the Google Fonts identity. We were looking for a balance between building something unique and original while avoiding user confusion.

While I did not hesitate choosing WordPress for the back-end, I didn’t want to use it on front end. We were aiming for an app-like experience and I, personally, wanted to code in JavaScript, using Vue.js in particular.

I came across an example of a website using NuxtJS with WordPress and decided to give it a try. The choice was made immediately. NuxtJS is a very popular Vue.js framework, and I really enjoy its simplicity and flexibility. 
I’ve been playing around with different NuxtJS settings to end up with a 100% static website. The fully static solution felt the most performant; the overall experience seemed the most fluid.That also means that my WordPress site is only used during the build process. Thus, it can run on my localhost. This is not negligible since it eliminates the hosting costs and most of all, lets me skip the security-related WordPress configuration and relieves me of the security-related stress. ;)

If you are familiar with NuxtJS, you probably know that the full static generation is not (yet) a part of NuxtJS. The prerendered pages try to fetch the data again when you are navigating.

That’s why we have to somehow “hack” the 100% static generation. In this case, we are saving the useful parts of the fetched data to a JSON file before each build process. This is possible, thanks to Nuxt hooks, in particular, its builder hooks.

Hooks are typically used in Nuxt modules:

/* modules/beforebuild.js */ const fs = require('fs') const axios = require('axios') const sourcePath = 'http://wpgoofonts.local/wp-json/wp/v2/' const path = 'static/allfonts.json' module.exports = () => { /* write data to the file, replacing the file if it already exists */ const storeData = (data, path) => { try { fs.writeFileSync(path, JSON.stringify(data)) } catch (err) { console.error(err) } } async function getData() { const fetchedTags = await axios.get(`${sourcePath}tags?per_page=500`) .catch(e => { console.log(e); return false }) /* build an object of tag_id: tag_slug */ const tags = fetchedTags.data.reduce((acc, cur) => { acc[cur.id] = cur.slug return acc }, {}) /* we want to know the total number or pages */ const mhead = await axios.head(`${sourcePath}posts?per_page=100`) .catch(e => { console.log(e); return false }) const totalPages = mhead.headers['x-wp-totalpages'] /* let's fetch all fonts */ let fonts = [] let i = 0 while (i < totalPages) { i++ const response = await axios.get(`${sourcePath}posts?per_page=100&page=${i}`) fonts.push.apply(fonts, response.data) } /* and reduce them to an object with entries like: {roboto: {name: Roboto, tags: ["clean","contemporary", ...]}} */ fonts = (fonts).reduce((acc, el) => { acc[el.slug] = { name: el.title.rendered, tags: el.tags.map(i => tags[i]), } return acc }, {}) /* save the fonts object to a .json file */ storeData(fonts, path) } /* make sure this happens before each build */ this.nuxt.hook('build:before', getData) } /* nuxt.config.js */ module.exports = { // ... buildModules: [ ['~modules/beforebuild'] ], // ... }

As you can see, we only request a list of tags and a list posts. That means we only use default WordPress REST API endpoints, and no configuration is required.

Final thoughts

Working on GooFonts was a long-term adventure. It is also this kind of projects that needs to be actively maintained. We regularly keep checking Google Fonts for the new typefaces, subsets, or variants. We tag new items and update our database. Recently, I was genuinely excited to discover that Bebas Neue has joint the family. We also have our personal favs among the much lesser-known specimens.

As a trainer that gives regular workshops, I can observe real users playing with GooFonts. At this stage of the project, we want to get as much feedback as possible. We would love GooFonts to be a useful, handy and intuitive tool for web designers. One of the to-do features is searching a font by its name. We would also love to add a possibility to share the bookmarked sets and create multiple "collections" of fonts.

As a developer, I truly enjoyed the multi-disciplinary aspect of this project. It was the first time I worked with the WordPress REST API, it was my first big project in Vue.js, and I learned so much about typography.  

Would we do anything differently if we could? Absolutely. It was a learning process. On the other hand, I don't think we would change the main tools. The flexibility of both WordPress and Nuxt.js proved to be the right choice. Starting over today, I would definitely took time to explore GraphQL, and I will probably implement it in the future.

I hope that you find some of the discussed methods useful. As I said before, your feedback is very precious. If you have any questions or remarks, please let me know in the comments!

The post How We Tagged Google Fonts and Created goofonts.com appeared first on CSS-Tricks.

How We Tagged Google Fonts and Created goofonts.com

Css Tricks - Wed, 01/15/2020 - 1:45pm

GooFonts is a side project signed by a developer-wife and a designer-husband, both of them big fans of typography. We’ve been tagging Google Fonts and built a website that makes searching through and finding the right font easier.

GooFonts uses WordPress in the back end and NuxtJS (a Vue.js framework) on the front end. I’d love to tell you the story behind goofonts.com and share a few technical details regarding the technologies we’ve chosen and how we adapted and used them for this project.

Why we built GooFonts

At the moment of writing this article, there are 977 typefaces offered by Google Fonts. You can check the exact number at any moment using the Google Fonts Developer API. You can retrieve the dynamic list of all fonts, including a list of the available styles and scripts for each family.

The Google Fonts website provides a beautiful interface where you can preview all fonts, sorting them by trending, popularity, date, or name. 

But what about the search functionality? 

You can include and exclude fonts by five categories: serif, sans-serif, display, handwriting, and monospace.

You can search within scripts (like Latin Extended, Cyrillic, or Devanagari (they are called subsets in Google Fonts). But you cannot search within multiple subsets at once.

You can search by four properties: thickness, slant, width, and "number of styles." A style, also called variant, refers both to the style (italic or regular) and weights (100, 200, up to 900). Often, the body font requires three variants: regular, bold, and italic. The “number of styles” property sorts out fonts with many variants, but it does not allow to select fonts that come in the “regular, bold, italic” combo.

There is also a custom search field where you can type your query. Unfortunately, the search is performed exclusively over the names of the fonts. Thus, the results often include font families uniquely from services other than Google Fonts. 

Let's take the "cartoon" query as an example. It results in "Cartoon Script" from an external foundry Linotype.

I can remember working on a project that demanded two highly stylized typefaces — one evoking the old Wild West, the other mimicking a screenplay. That was the moment when I decided to tag Google Fonts. :)

GooFonts in action

Let me show you how GooFonts works. The dark sidebar on the right is your  “search” area. You can type your keywords in the search field — this will perform an “AND” search. For example, you can look for fonts that are at once cartoon and slab. 

We handpicked a bunch of keywords — click any of them! If your project requires some specific subsets, check them in the subsets sections.  You can also check all the variants that you need for your font.

If you like a font, click its heart icon, and it will be stored in your browser’s localStorage. You can find your bookmarked fonts on the goofonts.com/bookmarks page. Together with the code, you might need to embed them.

How we built it: the WordPress part

To start, we needed some kind of interface where we could preview and tag each font. We also needed a database to store those tags. 

I had some experience with WordPress. Moreover, WordPress comes with its REST API,  which opens multiple possibilities for dealing with the data on the front end. That choice was made quickly.

I went for the most straightforward possible initial setup. Each font is a post, and we use post tags for keywords. A custom post type could have worked as well, but since we are using WordPress only for the data, the default content type works perfectly well.

Clearly, we needed to add all the fonts programmatically. We also needed to be able to programmatically update the fonts, including adding new ones or adding new available variants and subsets.

The approach described below can be useful with any other data available via an external API. In a custom WordPress plugin, we register a menu page from which we can check for updates from the API. For simplicity, the page will display a title, a button to activate the update and a progress bar for some visual feedback.

/** * Register a custom menu page. */ function register_custom_menu_page() { add_menu_page( 'Google Fonts to WordPress', 'WP GooFonts', 'manage_options', 'wp-goofonts-menu', function() { ?> <h1>Google Fonts API</h1> <button type="button" id="wp-goofonts-button">Run</button> <p id="info"></p> <progress id="progress" max="100" value="0"></progress> <?php } ); } add_action( 'admin_menu', 'register_custom_menu_page' );


Let's start by writing the JavaScript part. While most of the examples of using Ajax with WordPress implements jQuery and the jQuery.ajax method, the same can be obtained without jQuery, using axios and a small helper Qs.js for data serialization.

We want to load our custom script in the footer, after loading axios and qs:

add_action( 'admin_enqueue_scripts' function() { wp__script( 'axios', 'https://unpkg.com/axios/dist/axios.min.js' ); wp_enqueue_script( 'qs', 'https://unpkg.com/qs/dist/qs.js' ); wp_enqueue_script( 'wp-goofonts-admin-script', plugin_dir_url( __FILE__ ) . 'js/wp-goofonts.js', array( 'axios', 'qs' ), '1.0.0', true ); });

Let’s look how the JavaScript could look like:

const BUTTON = document.getElementById('wp-goofonts-button') const INFO = document.getElementById('info') const PROGRESS = document.getElementById('progress') const updater = { totalCount: 0, totalChecked: 0, updated: [], init: async function() { try { const allFonts = await axios.get('https://www.googleapis.com/webfonts/v1/webfonts?key=API_KEY&sort=date') this.totalCount = allFonts.data.items.length INFO.textContent = `Fetched ${this.totalCount} fonts.` this.updatePost(allFonts.data.items, 0) } catch (e) { console.error(e) } }, updatePost: async function(els, index) { if (index === this.totalCount) { return } const data = { action: 'goofonts_update_post', font: els[index], } try { const apiRequest = await axios.post(ajaxurl, Qs.stringify(data)) this.totalChecked++ PROGRESS.setAttribute('value', Math.round(100*this.totalChecked/this.totalCount)) this.updatePost(els, index+1) } catch (e) { console.error(e) } } } BUTTON.addEventListener('click', () => { updater.init() })

The init method makes a request to the Google Fonts API. Once the data from the API is available, we call the recursive asynchronous updatePost method that sends an individual font in the POST request to the WordPress server.

Now, it’s important to remember that WordPress implements Ajax in its specific way. First of all, each request must be sent to wp-admin/admin-ajax.php. This URL is available in the administration area as a global JavaScript variable ajaxurl.

Second, all WordPress Ajax requests must include an action argument in the data. The value of the action determines which hook tag will be used on the server-side.

In our case, the action value is goofonts_update_post. That means what happens on the server-side is determined by the wp_ajax_goofonts_update_post hook.

add_action( 'wp_ajax_goofonts_update_post', function() { if ( isset( $_POST['font'] ) ) { /* the post tile is the name of the font */ $title = wp_strip_all_tags( $_POST['font']['family'] ); $variants = $_POST['font']['variants']; $subsets = $_POST['font']['subsets']; $category = $_POST['font']['category']; /* check if the post already exists */ $object = get_page_by_title( $title, 'OBJECT', 'post' ); if ( NULL === $object ) { /* create a new post and set category, variants and subsets as tags */ goofonts_new_post( $title, $category, $variants, $subsets ); } else { /* check if $variants or $subsets changed */ goofonts_update_post( $object, $variants, $subsets ); } } }); function goofonts_new_post( $title, $category, $variants, $subsets ) { $post_id = wp_insert_post( array( 'post_author' => 1, 'post_name' => sanitize_title( $title ), 'post_title' => $title, 'post_type' => 'post', 'post_status' => 'draft', ) ); if ( $post_id > 0 ) { /* the easy part of tagging ;) append the font category, variants and subsets (these three come from the Google Fonts API) as tags */ wp_set_object_terms( $post_id, $category, 'post_tag', true ); wp_set_object_terms( $post_id, $variants, 'post_tag', true ); wp_set_object_terms( $post_id, $subsets, 'post_tag', true ); } }

This way, in less than a minute, we end up with almost one thousand post drafts in the dashboard — all of them with a few tags already in place. And that’s the moment when the crucial, most time-consuming part of the project begins. We need to start manually add tags for each font one by one.
The default WordPress editor does not make much sense in this case. What we needed is a preview of the font. A link to the font’s page on fonts.google.com also comes in handy.

custom meta box does the job very well. In most cases, you will use meta boxes for custom form elements to save some custom data related to the post. In fact, the content of a meta box can be practically any HTML.

function display_font_preview( $post ) { /* font name, for example Abril Fatface */ $font = $post->post_title; /* font as in url, for example Abril+Fatface */ $font_url_part = implode( '+', explode( ' ', $font )); ?> <div class="font-preview"> <link href="<?php echo 'https://fonts.googleapis.com/css?family=' . $font_url_part . '&display=swap'; ?>" rel="stylesheet"> <header> <h2><?php echo $font; ?></h2> <a href="<?php echo 'https://fonts.google.com/specimen/' . $font_url_part; ?>" target="_blank" rel="noopener">Specimen on Google Fonts</a> </header> <div contenteditable="true" style="font-family: <?php echo $font; ?>"> <p>The quick brown fox jumps over a lazy dog.</p> <p style="text-transform: uppercase;">The quick brown fox jumps over a lazy dog.</p> <p>1 2 3 4 5 6 7 8 9 0</p> <p>& ! ; ? {}[]</p> </div> </div> <?php } add_action( 'add_meta_boxes', function() { add_meta_box( 'font_preview', /* metabox id */ 'Font Preview', /* metabox title */ 'display_font_preview', /* content callback */ 'post' /* where to display */ ); });

Tagging fonts is a long-term task with a lot of repetition. It also requires a big dose of consistency. That’s why we started by defining a set of tag “presets.” That could be, for example:

{ /* ... */ comic: { tags: 'comic, casual, informal, cartoon' }, cursive: { tags: 'cursive, calligraphy, script, manuscript, signature' }, /* ... */ }

Next with some custom CSS and JavaScript, we “hacked” the WordPress editor and tags form by enriching it with the set of preset buttons. 

How we built it: The front end part (using NuxtJS)

The goofonts.com interface was designed by Sylvain Guizard, a french graphic and web designer (who also happens to be my husband). We wanted something simple with a distinguished “search” area. Sylvain deliberately went for colors that are not too far from the Google Fonts identity. We were looking for a balance between building something unique and original while avoiding user confusion.

While I did not hesitate choosing WordPress for the back-end, I didn’t want to use it on front end. We were aiming for an app-like experience and I, personally, wanted to code in JavaScript, using Vue.js in particular.

I came across an example of a website using NuxtJS with WordPress and decided to give it a try. The choice was made immediately. NuxtJS is a very popular Vue.js framework, and I really enjoy its simplicity and flexibility. 
I’ve been playing around with different NuxtJS settings to end up with a 100% static website. The fully static solution felt the most performant; the overall experience seemed the most fluid.That also means that my WordPress site is only used during the build process. Thus, it can run on my localhost. This is not negligible since it eliminates the hosting costs and most of all, lets me skip the security-related WordPress configuration and relieves me of the security-related stress. ;)

If you are familiar with NuxtJS, you probably know that the full static generation is not (yet) a part of NuxtJS. The prerendered pages try to fetch the data again when you are navigating.

That’s why we have to somehow “hack” the 100% static generation. In this case, we are saving the useful parts of the fetched data to a JSON file before each build process. This is possible, thanks to Nuxt hooks, in particular, its builder hooks.

Hooks are typically used in Nuxt modules:

/* modules/beforebuild.js */ const fs = require('fs') const axios = require('axios') const sourcePath = 'http://wpgoofonts.local/wp-json/wp/v2/' const path = 'static/allfonts.json' module.exports = () => { /* write data to the file, replacing the file if it already exists */ const storeData = (data, path) => { try { fs.writeFileSync(path, JSON.stringify(data)) } catch (err) { console.error(err) } } async function getData() { const fetchedTags = await axios.get(`${sourcePath}tags?per_page=500`) .catch(e => { console.log(e); return false }) /* build an object of tag_id: tag_slug */ const tags = fetchedTags.data.reduce((acc, cur) => { acc[cur.id] = cur.slug return acc }, {}) /* we want to know the total number or pages */ const mhead = await axios.head(`${sourcePath}posts?per_page=100`) .catch(e => { console.log(e); return false }) const totalPages = mhead.headers['x-wp-totalpages'] /* let's fetch all fonts */ let fonts = [] let i = 0 while (i < totalPages) { i++ const response = await axios.get(`${sourcePath}posts?per_page=100&page=${i}`) fonts.push.apply(fonts, response.data) } /* and reduce them to an object with entries like: {roboto: {name: Roboto, tags: ["clean","contemporary", ...]}} */ fonts = (fonts).reduce((acc, el) => { acc[el.slug] = { name: el.title.rendered, tags: el.tags.map(i => tags[i]), } return acc }, {}) /* save the fonts object to a .json file */ storeData(fonts, path) } /* make sure this happens before each build */ this.nuxt.hook('build:before', getData) } /* nuxt.config.js */ module.exports = { // ... buildModules: [ ['~modules/beforebuild'] ], // ... }

As you can see, we only request a list of tags and a list posts. That means we only use default WordPress REST API endpoints, and no configuration is required.

Final thoughts

Working on GooFonts was a long-term adventure. It is also this kind of projects that needs to be actively maintained. We regularly keep checking Google Fonts for the new typefaces, subsets, or variants. We tag new items and update our database. Recently, I was genuinely excited to discover that Bebas Neue has joint the family. We also have our personal favs among the much lesser-known specimens.

As a trainer that gives regular workshops, I can observe real users playing with GooFonts. At this stage of the project, we want to get as much feedback as possible. We would love GooFonts to be a useful, handy and intuitive tool for web designers. One of the to-do features is searching a font by its name. We would also love to add a possibility to share the bookmarked sets and create multiple "collections" of fonts.

As a developer, I truly enjoyed the multi-disciplinary aspect of this project. It was the first time I worked with the WordPress REST API, it was my first big project in Vue.js, and I learned so much about typography.  

Would we do anything differently if we could? Absolutely. It was a learning process. On the other hand, I don't think we would change the main tools. The flexibility of both WordPress and Nuxt.js proved to be the right choice. Starting over today, I would definitely took time to explore GraphQL, and I will probably implement it in the future.

I hope that you find some of the discussed methods useful. As I said before, your feedback is very precious. If you have any questions or remarks, please let me know in the comments!

The post How We Tagged Google Fonts and Created goofonts.com appeared first on CSS-Tricks.

A Web Component with Different HTML for Desktop and Mobile

Css Tricks - Wed, 01/15/2020 - 1:44pm

Christian Schaefer has a great big write-up about dealing with web advertisements. The whole thing is interesting, first documenting all the challenges that ads present, and then presenting modern solutions to each of them.

One code snippet that caught my eye was a simple way to design a component that renders different HTML depending on the screen size.

<div class="ad"> <template class="ad__mobile"> // Mobile ad HTML code with inline script </template> <template class="ad__desktop"> // Desktop ad HTML code with inline script </template> <script> const isMobile = matchMedia('(max-device-width: 20em)').matches; const ad = document.currentScript.closest('.ad'); const content = ad .querySelector(isMobile ? '.ad__mobile' : '.ad__desktop') .content; ad.appendChild(document.importNode(content, true)); </script> </div>

Clever. Although note that Christian ends up going a totally different route in the article.

Here's that same code where I use a custom element and move the JavaScript to JavaScript just 'cuz.

See the Pen
A Web Component with Different HTML for Desktop and Mobile
by Chris Coyier (@chriscoyier)
on CodePen.

The post A Web Component with Different HTML for Desktop and Mobile appeared first on CSS-Tricks.

A Web Component with Different HTML for Desktop and Mobile

Css Tricks - Wed, 01/15/2020 - 1:44pm

Christian Schaefer has a great big write-up about dealing with web advertisements. The whole thing is interesting, first documenting all the challenges that ads present, and then presenting modern solutions to each of them.

One code snippet that caught my eye was a simple way to design a component that renders different HTML depending on the screen size.

<div class="ad"> <template class="ad__mobile"> // Mobile ad HTML code with inline script </template> <template class="ad__desktop"> // Desktop ad HTML code with inline script </template> <script> const isMobile = matchMedia('(max-device-width: 20em)').matches; const ad = document.currentScript.closest('.ad'); const content = ad .querySelector(isMobile ? '.ad__mobile' : '.ad__desktop') .content; ad.appendChild(document.importNode(content, true)); </script> </div>

Clever. Although note that Christian ends up going a totally different route in the article.

Here's that same code where I use a custom element and move the JavaScript to JavaScript just 'cuz.

See the Pen
A Web Component with Different HTML for Desktop and Mobile
by Chris Coyier (@chriscoyier)
on CodePen.

The post A Web Component with Different HTML for Desktop and Mobile appeared first on CSS-Tricks.

The Deal with the Section Element

Css Tricks - Wed, 01/15/2020 - 5:20am

Two articles published the exact same day:

  1. Bruce Lawson on Smashing Magazine: Why You Should Choose HTML5 <article> Over <section>
  2. Adam Laki on Pine: The Difference Between <section> and <div> Element

They are comparing slightly different things, but they both involve the <section> element.

I find it pretty clear when you reach for a <div>: When you want that element to be essentially meaningless. You're only using it for styling purposes.

I always think of RSS when I think of <article>: Would this little bit of stuff make sense as an entry (which doesn't necessarily need to be the entire content of the article)? If yes, use <article>; if not, don't.

Bruce has a go-to answer:

[...] think of <article> not just as a newspaper article, or a blog post, but as an article of clothing — a discrete entity that can be reused in another context. So your trousers are an article, and you can wear them with a different outfit; your shirt is an article, and can be worn with different trousers; your knee-length patent leather stiletto boots are an article.

More importantly, it has some actual functionality. Bruce mentions that Apple WatchOS specifically uses it to find content on pages.

But <section> is more nebulous. At one point, you were supposed to think of sections as places where your <h1>-<h6> headings would reset, but that never came to fruition because it required a thing called "HTML5 Outlining" which zero browsers support.

So should we use <section> it at all? According to Bruce, sometimes! Smashing Magazine's design for articles has a summary at the beginning of the article. Visually, that's fairly clear, but less-so for screen reader users. The solution was wrapping the summary in an element with an aria-label to make that clear. But you aren't supposed to use aria-label unless that element also has a role. You could apply a role to a <div>, but <section> already has a good default role, so:

<section aria-label="quick summary"> Summary text </section>

Adam's article (sorry, Adam) is very vague on the points.

The main difference comes from the semantic. If you have a part in your site or application which has its logic you need to use the <section> tag to declare it...

... use <section> when it is logically correct to make a part of your site or app readable to the assistive technology. It is an excellent approach if you keep in mind the screen readers.

So you get a role="region" automatically for sections, but I'm not sure that does anything for screen readers, sans the label. In a quick test (Chrome for desktop with VoiceOver enabled), a <section> without an aria-label just wasn't there in the Landmarks section of the Web Rotor, but it showed up once it had an aria-label.

Point is: don't just use <section> and assume you're doing something good for accessibility. Its purpose is pretty limited and only useful for establishing landmarks. Even then, you aren't helping that much. Leonie Watson in the comments:

When the choice is between a visually hidden heading and a section element with an accessible name there are a couple of things to consider before deciding which approach is the right one.

When a section element has an accessible name it becomes a navigable landmark element, so a screen reader user can use their screen reader's shortcut key for navigating from one to the next - just like they can do with headings.

According to the most recent WebAIM screen reader user survey though, 68% of screen reader users prefer to navigate by headings compared to 2.9% who prefer landmarks.

So from a strict accessibility point of view, you could probably drop the heading, but from a usability point of view you really want to keep the heading - at least until more screen reader users express a preference for using landmarks to navigate content.

The post The Deal with the Section Element appeared first on CSS-Tricks.

The Deal with the Section Element

Css Tricks - Wed, 01/15/2020 - 5:20am

Two articles published the exact same day:

  1. Bruce Lawson on Smashing Magazine: Why You Should Choose HTML5 <article> Over <section>
  2. Adam Laki on Pine: The Difference Between <section> and <div> Element

They are comparing slightly different things, but they both involve the <section> element.

I find it pretty clear when you reach for a <div>: When you want that element to be essentially meaningless. You're only using it for styling purposes.

I always think of RSS when I think of <article>: Would this little bit of stuff make sense as an entry (which doesn't necessarily need to be the entire content of the article)? If yes, use <article>; if not, don't.

Bruce has a go-to answer:

[...] think of <article> not just as a newspaper article, or a blog post, but as an article of clothing — a discrete entity that can be reused in another context. So your trousers are an article, and you can wear them with a different outfit; your shirt is an article, and can be worn with different trousers; your knee-length patent leather stiletto boots are an article.

More importantly, it has some actual functionality. Bruce mentions that Apple WatchOS specifically uses it to find content on pages.

But <section> is more nebulous. At one point, you were supposed to think of sections as places where your <h1>-<h6> headings would reset, but that never came to fruition because it required a thing called "HTML5 Outlining" which zero browsers support.

So should we use <section> it at all? According to Bruce, sometimes! Smashing Magazine's design for articles has a summary at the beginning of the article. Visually, that's fairly clear, but less-so for screen reader users. The solution was wrapping the summary in an element with an aria-label to make that clear. But you aren't supposed to use aria-label unless that element also has a role. You could apply a role to a <div>, but <section> already has a good default role, so:

<section aria-label="quick summary"> Summary text </section>

Adam's article (sorry, Adam) is very vague on the points.

The main difference comes from the semantic. If you have a part in your site or application which has its logic you need to use the <section> tag to declare it...

... use <section> when it is logically correct to make a part of your site or app readable to the assistive technology. It is an excellent approach if you keep in mind the screen readers.

So you get a role="region" automatically for sections, but I'm not sure that does anything for screen readers, sans the label. In a quick test (Chrome for desktop with VoiceOver enabled), a <section> without an aria-label just wasn't there in the Landmarks section of the Web Rotor, but it showed up once it had an aria-label.

Point is: don't just use <section> and assume you're doing something good for accessibility. Its purpose is pretty limited and only useful for establishing landmarks. Even then, you aren't helping that much. Leonie Watson in the comments:

When the choice is between a visually hidden heading and a section element with an accessible name there are a couple of things to consider before deciding which approach is the right one.

When a section element has an accessible name it becomes a navigable landmark element, so a screen reader user can use their screen reader's shortcut key for navigating from one to the next - just like they can do with headings.

According to the most recent WebAIM screen reader user survey though, 68% of screen reader users prefer to navigate by headings compared to 2.9% who prefer landmarks.

So from a strict accessibility point of view, you could probably drop the heading, but from a usability point of view you really want to keep the heading - at least until more screen reader users express a preference for using landmarks to navigate content.

The post The Deal with the Section Element appeared first on CSS-Tricks.

Debunking the Myth: Accessibility and React

Css Tricks - Wed, 01/15/2020 - 5:20am

I find it notable when the blog of a major accessibility-focused company like Deque publishes an article called Debunking the Myth: Accessibility and React. Mark Steadman is essentially saying if a site has bad accessibility, it ain't React... it's you. The tools are there to achieve good accessibility.

React didn't use a <div> for a <button>, you did. React didn't force extra markup all over the page when you decided to not use a Fragment. React didn't forget to change the title of the page because that was something you neglected.

Is it different how you have to do it in React versus how you have to do it in some other framework or CMS? Yes, it is. Different, but neither worse nor harder.

I'm optimistic that well-made React components focused on accessibility can have a positive impact on the web. Just today I was pair programming and looking at some HTML for a toggle UI in a Rails template. It had a little bug we wanted to fix, which required an HTML change. But this toggle wasn't a component, it was a chunk of HTML used in dozens of places on the site. Gosh, did I wish this part of the site was architected with a proper components instead, so the change would have fixed all toggles on the site at once. All JavaScript frameworks encourage this kind of component building, which is just smart front-end architecture if you ask me.

Where did the bad wrap on React come from? Well, we could debate that for days. Is it that JavaScript-focused developers never got the HTML training they needed? Maybe. Was it gnarly, unsemantic React code that was written/shared in the early days that others copy and pasted too many times? Maybe. I'm not sure we'll ever know. The important thing is that we all do a better job now.

Direct Link to ArticlePermalink

The post Debunking the Myth: Accessibility and React appeared first on CSS-Tricks.

Debunking the Myth: Accessibility and React

Css Tricks - Wed, 01/15/2020 - 5:20am

I find it notable when the blog of a major accessibility-focused company like Deque publishes an article called Debunking the Myth: Accessibility and React. Mark Steadman is essentially saying if a site has bad accessibility, it ain't React... it's you. The tools are there to achieve good accessibility.

React didn't use a <div> for a <button>, you did. React didn't force extra markup all over the page when you decided to not use a Fragment. React didn't forget to change the title of the page because that was something you neglected.

Is it different how you have to do it in React versus how you have to do it in some other framework or CMS? Yes, it is. Different, but neither worse nor harder.

I'm optimistic that well-made React components focused on accessibility can have a positive impact on the web. Just today I was pair programming and looking at some HTML for a toggle UI in a Rails template. It had a little bug we wanted to fix, which required an HTML change. But this toggle wasn't a component, it was a chunk of HTML used in dozens of places on the site. Gosh, did I wish this part of the site was architected with a proper components instead, so the change would have fixed all toggles on the site at once. All JavaScript frameworks encourage this kind of component building, which is just smart front-end architecture if you ask me.

Where did the bad wrap on React come from? Well, we could debate that for days. Is it that JavaScript-focused developers never got the HTML training they needed? Maybe. Was it gnarly, unsemantic React code that was written/shared in the early days that others copy and pasted too many times? Maybe. I'm not sure we'll ever know. The important thing is that we all do a better job now.

Direct Link to ArticlePermalink

The post Debunking the Myth: Accessibility and React appeared first on CSS-Tricks.

How many CSS properties are there?

Css Tricks - Tue, 01/14/2020 - 5:14pm

Tomasz ?akomy posted a joke tweet about naming all the CSS attributes and Tejas Kumar replied with a joke answer, going as far as making an npm module. You can even run a terminal command to see them:

npx get-all-css-properties

You'll get 259 of them. The source code uses the website quackit.com for the data, which I'd never heard of. &#x1f937;‍♂️

I would have probably looked at MDN, where some quick querySelectorAll handiwork in the console yields a different number: 584. But ooops, that's full of selectors, at-rules, and other stuff. Their reference only lists 72, but says it's incomplete.

W3Schools lists 228 of them. HTML Dog lists 125. Our almanac has 176, and I know we omit stuff on purpose (e.g. we file margin-left under margin instead of making its own entry).

The horse's mouth?

520 distinct property names from 66 technical reports and 66 editors' drafts.

The post How many CSS properties are there? appeared first on CSS-Tricks.

Business Dad

Css Tricks - Tue, 01/14/2020 - 5:13pm

Congrats to Chris Enns, our podcast editor on ShopTalk and CodePen Radio, for landing a really cool new podcast to edit: Business Dad. It's Alexis Ohanian, the co-founder of Reddit, talking to dads. The first episode is with Hasan Minhaj(!)

Speaking of podcasting, Dave wrote up his thoughts on starting a podcast (you should), a beefier and more interesting version of my little writeup. I stand by my $1,000 podcasting setup though. I still use it and think it's quite nice.

Direct Link to ArticlePermalink

The post Business Dad appeared first on CSS-Tricks.

A Trick That Makes Drawing SVG Lines Way Easier

Css Tricks - Tue, 01/14/2020 - 6:55am

When drawing lines with SVG, you often have a <path> element with a stroke. You set a stroke-dasharray that is as long as the path itself, as well as a stroke-offset that extends so far that you that it's initially hidden. Then you animate the stroke-offset back to 0 so you can watch it "draw" the shape.

Figuring out the length of the path is the trick, which fortunately you can do in JavaScript by selecting the path and doing pathEl.getTotalLength(). It'll probably be some weird decimal. A smidge unfortunate we can't get that in CSS, but c'est la vie.

Here's the trick!

You don't have to measure the length of the path, because you can set it.

So you do like:

<path d="M66.039,133.545 ... " pathLength="1" />

That doesn't do anything by itself (as far as I know). It's not like that only draws part of the path — it still draws the whole thing like as if you did nothing, only now the "math" of the path length is based on a value of 1.

Now we can set the stroke-dasharray to 1, and animate the offset in CSS!

.path { stroke-dasharray: 1; stroke-dashoffset: 1; animation: dash 5s linear alternate infinite; } @keyframes dash { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }

Which works:

See the Pen
Basic Example of SVG Line Drawing, Backward and Forward
by Chris Coyier (@chriscoyier)
on CodePen.

High five to Adam Haskell who emailed me about this a few months back.

Hey, speaking of SVG line drawing: Lemonade made a landing page for their 2019 charity that uses scroll-triggered SVG line drawing up and down the entire page. They did a behind-the-scenes look at it, which I always appreciate.

The post A Trick That Makes Drawing SVG Lines Way Easier appeared first on CSS-Tricks.

In Defence of “Serverless” —the term

Css Tricks - Tue, 01/14/2020 - 6:55am

Ben Ellerby:

For now Serverless, to me at least, manages to do a hard job, defining the borders of a very fluid and complex space of possible solutions in which we can build next-generation architectures. It would help if there was not a framework of the same name, it would help if people didn’t first hear it synonymous with Lambda and it would help if people stopped saying “but you know there are servers…”. That being said, I’ve not heard a better proposal yet!

I like the term (we got the whole site and all) but rather than explain why, I'll let my most popular tweet of all time take it from here:

Rather than alt text, here's the whole conversation in the format of the
American Chopper Argument meme.

Why would you call it "serverless" when the architecture is anything but?

They aren't yours. You don't manage them. You barely think about them.

I DON'T THINK ABOUT AIR EITHER BUT WE DON'T LIVE IN AN AIRLESS WORLD.

It's just an effective buzzword. It evokes a whole ecosystem in a single word.

I BET YOU SAY "THE CLOUD" UNIRONICALLY TOO U PLEEB.

Direct Link to ArticlePermalink

The post In Defence of “Serverless” —the term appeared first on CSS-Tricks.

Netlify High-Fives

Css Tricks - Tue, 01/14/2020 - 6:53am

We've got Netlify as a sponsor around here again this year, which is just fantastic. Big fan. Our own Sarah Drasner is Head of DX (Developer Experience) over there, if you hadn't heard. And if you haven't heard of Netlify, well, you're in for a treat. It's a web host, but for your jamstack sites, which means it's static hosting, encouraging you to pre-build as much of your site as you can, then use JavaScript and APIs to do whatever else you need to. Heck, they'll help you build serverless functions and auth.

Here's a couple of Netlify-related things swirling around in my life.

  • I added open authoring to our conference site. So now, anybody can go to the admin area, auth with GitHub, and submit a conference. No coding required. Dream come true, if you ask me. The same thing is live on the serverless site.
  • I enjoyed Bryan Robinson's take on jamstack in 2020. It's about the connection between services and the power that brings.
  • It's interesting how even not-particularly jamstack-y software like WordPress can totally live a jamstack life, when you combine it with something like Gatsby.
  • I have a new microsite idea cooking. I really wanna build a site that showcases all the things you can (and probably should) be doing with your build process. It will explain them and provide resources, but the whole site will dogfood itself and do all those things. Stuff like:
    1. Process all it's code, keeping compiled code out of the repo
    2. Build a sitemap
    3. Optimize all the images
    4. Check for broken links
    5. Run accessibility tests
    6. Check the performance budget
    7. Run unit test
    8. Run end-to-end tests
    9. Run visual regression tests
    10. Trigger notifications

Wouldn't that last one be cool?! We'd do it all with build plugins, at least that's how it works in my mind. If you have a strong desire to contribute, lemme know — maybe we can make it a community effort.

The post Netlify High-Fives appeared first on CSS-Tricks.

Snowpack

Css Tricks - Mon, 01/13/2020 - 6:23pm

Snowpack. Love that name. This is the new thing from the Pika people, who are on to something. It's a bundler alternative, in a sense. It runs over packages you pull from npm to make sure that they are ES module-compatible (native imports).

This is how I digest it. When you write a line of code like:

import React from "react";

That's actually invalid JavaScript. It looks like a native import, but it isn't. (It would start with a filepath character like ./ and end in .js to be valid.) It's just an agreement from Big Bundler like, "Oh, I know what you mean. You mean I should go look in node_modules for this thing." Then it goes and does it.

A lot of stuff on npm isn't ready for ES modules. It's in some other module format (e.g. CommonJS) and assumes you'll be using a bundler with it. An assumption served them just fine for a while, but it's an assumption that is starting to be a bit of a thorn for front-end developers.

UNPKG has had a feature where you could add ?module to the end of their URLs to get it to serve up an ES module-friendly version of the package, but it's been in an experimental stage for a long time because, presumably, it's a hard problem to solve. Which packages are ready for ES modules? Can they be processed to be ready on the fly?

Even the Pika CDN doesn't solve the issues of packages that aren't written to be used via ES modules. For example, since React isn't written to be used with ES modules directly, so you just can't (but you can still use it via <script> tag).

Snowpack has apparently dealt with this. It runs its magic over the packages that you install (locally) and prepares them for ES module usage. So, after Snowpack has ran, now you can do this (which you haven't been able to do before):

import React from '/web_modules/react.js';

Which is valid code for ES modules. Plus, if you run Babel anyway, you don't even have to change that original line.

Hence their marketing/explanation:

1) Instead of bundling on every change, just run Snowpack once right after npm install.
2) Snowpack re-installs your dependencies as single JS files to a new web_modules/ directory.
3) Write code, import those dependencies via an ESM import, and then run it all in the browser.
4) Skip the bundle step and see your changes reflected in the browser immediately after hitting save.
5) Keep using your favorite web frameworks and build tools! Babel & TypeScript supported.

It's kinda like you get native code splitting for free, and you're just crossing your fingers that ES modules will be just as fast as bundling with that benefit. I'm optimistic. I think it's early days and would be nervous on Big Production Stuff, but I also think native ES modules are probably the future.

The post Snowpack appeared first on CSS-Tricks.

Animate Text on Scroll

Css Tricks - Mon, 01/13/2020 - 11:02am

We covered the idea of animating curved text not long ago when a fun New York Times article came out. All I did was peek into how they did it and extract the relevant parts to a more isolated demo.

That demo is here:

See the Pen
Selfie Crawl
by Chris Coyier (@chriscoyier)
on CodePen.

@keyframers covered it much nicer than I did and made this video. (Seriously, it's so clear and concise — it's a great watch.)

I particularly like how quick'n'easy creating, exporting, optimizing, and integrating the actual SVG codes in their demonstration.

Their final demo:

See the Pen
SVG textPath Animation on Scroll Tutorial | Keyssentials: Web Animation Tips by @keyframers
by @keyframers (@keyframers)
on CodePen.

The post Animate Text on Scroll appeared first on CSS-Tricks.

A Scandal in Bohemia

Css Tricks - Mon, 01/13/2020 - 11:02am

I love that Paravel is so busy doing so much cool stuff they literally just forgot that they built this and are just now releasing it.

It's a Sherlock Holmes story, but designed to be more interesting and immersive (even audio!) than just words-on-a-screen.

Direct Link to ArticlePermalink

The post A Scandal in Bohemia appeared first on CSS-Tricks.

Syndicate content
©2003 - Present Akamai Design & Development.