Web Standards

Conversational UX Design : An Introduction

Usability Geek - Wed, 06/20/2018 - 9:48am
Conversational user experience (UX) design has recently become a central part of discussions throughout the tech community. Web developers and designers are working to create technology that can...
Categories: Web Standards

UTC is Enough for Everyone, Right?

Css Tricks - Wed, 06/20/2018 - 8:06am

A good candidate for the Blog Post of the Year from Zach Holman. I think Eric Portis' "w descriptors and sizes: Under the hood" is up there too, but perhaps even nerdier. Ooooh, also Frank Chimero's "The Good Room" is up there. But I digress.

Zach's article is as educational as it is funny.

But yeah, this UTC initialism doesn’t make any sense. Let’s dig into this a little more.

So you’ve got a bunch of scientist types around 1960 who are like, hey, time is all screwy we should totes make a standard. And some of them spoke English, and some of them spoke French, which, of course, is the cause of so much conflict over so many generations. (In hindsight, maybe we should have split all those troublemakers up from the start.)

The English-speaking folk were like yo, this definitely sounds like Coordinated Universal Time, boom, ship it. And the French speakers were like yeah that makes total sense! Temps Universel Coordonné DOES work out well in our language, too, ship it! Then they both looked up and realized cool, they’ve created both CUT and TUC for acronyms. Shit.

When your standard — that is expressly meant to standardize time — doesn’t even standardize on a standard acronym, well, damn, that probably doesn’t bode well for your standard.

It's a big custom-designed multimedia adventure, not to mention a clever bit of content marketing done right.

Direct Link to ArticlePermalink

The post UTC is Enough for Everyone, Right? appeared first on CSS-Tricks.

Centering: The Newest Coolest Way vs. The Oldest Coolest Way

Css Tricks - Wed, 06/20/2018 - 4:00am

This isn't a comprehensive guide to centering things. We have that!

This is just a little observation about old and new. One of the trickier things related to centering in CSS is when you need to center both vertically and horizontally and you don't know the width or height of what you are centering. Vertical centering being the extra tricky of the two.

Believe it or not, there was a way to do that even in IE 8. The trick was taking advantage of display: table; and that tables had this other property, vertical-align: middle;, which could be used for vertical centering.

Say all you wanted to do was center a sentence perfectly in the middle of the browser window:

... <body> <span> Centered vertically and horizontally. </span> </body> ...

You could do that like this:

html, body { margin: 0; height: 100%; } body { display: table; width: 100%; } body > span { display: table-cell; vertical-align: middle; text-align: center; }

That might be the oldest trick in the Book of CSS Centering. Here it is working in IE 8:

Today we have more modern layout methods. Flexbox! CSS grid!

Here's accomplishing the same thing with the most modern methods available:

body { display: grid; height: 100vh; margin: 0; place-items: center center; }

We don't even need to touch the span there! This is so cutting edge, in fact, that Microsoft Edge, which supports CSS grid, doesn't support place-items yet. You'd have to use align-items: center; and justify-content: center; instead.

Always movin'.

The post Centering: The Newest Coolest Way vs. The Oldest Coolest Way appeared first on CSS-Tricks.

Don’t just copy the @font-face out of Google Fonts URLs

Css Tricks - Tue, 06/19/2018 - 6:16am

I don't think this is an epidemic or anything, but I've seen it done a few times and even advocated for. This is what I mean...

You go to Google Fonts and pick a font like Open Sans, and it gives you either a <link> or an @import with a URL there in which to ready this font for usage on your site.

You can take a peek in there and see what it returns...

It's just some @font-face declarations, of course!

Now your performance-minded brain kicks off. Wait. So, I make one HTTP request for this stylesheet, and then it makes more HTTP requests for those woff2 files it's linking up. Screw the middle man here, why not just copy those @font-face blocks right out of here and use them.

You can! But!

The issue is that Google does fancy Google things here and the contents of that original stylesheet changes based on the browser requesting it. That screenshot above is Chrome 66. Here's Firefox 20 on Windows 7:

It's different! It's only got woff, not woff2. If we open that URL in IE 8, we'd get an @font-face block that includes the eot format!

The point is, what that URL gives is very specific to what the current browser needs. That's a pretty cool thing to abstract away and not worry about. Should new browsers have new formats and new CSS syntax needed, that'll just come along for the ride.

Not that Google Fonts is perfect with this stuff. For example, by not controlling your own @font-face blocks, you can't take advantage of font-display, which is a shame. Maybe we'll get that someday, or maybe it's worth self-hosting your Google Fonts, which is another whole thing we'll get into someday.

The post Don’t just copy the @font-face out of Google Fonts URLs appeared first on CSS-Tricks.

The Four Big Ways Jetpack Helps with Image Performance

Css Tricks - Tue, 06/19/2018 - 5:18am

We've been working with Jetpack around here as a sponsor. It's a great match because as someone with a bunch of self-hosted WordPress sites, Jetpack is one of those no-brainer plugins for me. Jetpack can do a ton of good things for any site in a variety of very different ways. Here's one way to think about it: it brings the power of WordPress' own massive servers to you.

For now, let's just focus on one angle of what Jetpack can do for you: image performance. Jetpack does a ton for you in this regard, solving some non-trivial performance upgrades. Let's take a look at what I see as the four big boosts you get from Jetpack on your images.

1) WordPress does responsive images for you

OK, I cheated with the first one because you don't actually need Jetpack to benefit from this. But it's an important and foundational concept for fast images. Just by using WordPress, you get basic responsive images for free.

If you already know what I'm talking about, here's an example of the output you'll see in the DOM of a published WordPress post with an image in it uploaded via the Media Uploader:

It's wonderful to get this for free, as writing out responsive images syntax by hand is quite cumbersome.

If you are new to the idea of responsive images, the big idea is this: rather than a single image going to any browser visiting your website, you have multiple images in different sizes and the most-correct one is delivered. Imagine instead of a mobile phone downloading a 1600 pixel wide image (way bigger than it needs), it only downloads a 320-pixel wide image, saving a ton of downloading time.

We've written lots about responsive images over the years.

2) You get a CDN

Read a bit about web performance and you'll be unanimously told: "use a CDN." A CDN is a Content Delivery Network, essentially web servers designed specifically to make serving assets like images super fast. They call it a network because it isn't just one server, it's many servers physically located all over the world so that when your website is requested from different locations all around the world, the files being sent back come from geographically closer locations (faster!). Not to mention it does other clever things like not requiring cookies for each web request like your own server probably does.

Literally, flip a switch in Jetpack and you'll be using an image CDN:

It's called Photon.

Site speed is impacted by many factors and one of them is content delivery. Using what is referred to as a content delivery network (or CDN) helps by:

  • Delivering your content from high-speed and dedicated data centers.
  • More files can be downloaded simultaneously by the browser.
  • Distributed data centers (ie in different geographic locations) improve download speeds and provide redundancy.
  • By distributing load and save bandwidth you reduce your existing hosting costs (or keep them in check).
3) You get optimization

Una Kravets calls image optimization an easy performance win for designers. It's an easy thing to see. Try taking a screenshot of something, exporting something from Photoshop, or grabbing some stock photography. Then drop it onto a tool like ImageOptim and watch the bytes fall away as it optimizes it. Massive savings.

But wouldn't it be nice if it wasn't on you to manually optimize all your images before using them? Computers are supposed to help us with menial tasks, right?! When you flip on the CDN feature of Jetpack, your images are now hosted on Photon, and you can see in the Photon docs how it handles things like resizing and quality for you.

4) You get lazy loading

Lazy loading is the idea that you don't load anything at all unless you need it. In the case of images, don't download the image unless it's visible on the page. As in, don't download an image that is three quarter down an article that a user might never scroll down to, but if they do, then download it.

You know what they say, the fastest web request is one that is never made. Jeremy Wagner, for Google, says:

When we lazy load images and video, we reduce initial page load time, initial page weight, and system resource usage, all of which have positive impacts on performance.

This is another flip-a-switch feature that works on any theme. Turn it on, you got lazy loading.

All Together Now
  1. You get responsive images with WordPress, which by itself can be a major performance win.
  2. With Jetpack, those responsive images are CDN-hosted, providing a speed boost and great caching for the images that are downloaded.
  3. Just because you're using responsive images and a CDN doesn't automatically mean those images are optimized, but they are on Photon.
  4. Last, nothing is downloaded at all unless the images are in view (lazy loading), which is the most efficient thing you can do.

Pretty compelling.

The post The Four Big Ways Jetpack Helps with Image Performance appeared first on CSS-Tricks.

Building a RSS Viewer With Vue: Part 2

Css Tricks - Tue, 06/19/2018 - 3:56am

Welcome to Part 2 of this mini-series on building a RSS viewer with Vue. In the last post, I walked through how I built my demo using Vue.js and Vuetify on the front end and Webtask on the back end. When I built that initial version, I knew it was exactly thatmdash;an "initial" version. I took some time to work on a few updates, and while I won't dare call this a "perfect" version, I do think I've made some improvements and I'd like to share them with you.

Article Series:
  1. Setup and first iteration
  2. Refinements and final version (This Post)

Before I get started, here are links to the completed demo and source code.

View Demo View Code

Feel free to fork, file PRs, and report bugs to your heart's content!

The Plan

When I shared the initial version in Part 1, I outlined some ideas to improve the RSS reader, including:

  • Moving to Vuex.
  • Starting to switch to components in the layout. (Well, I was already using Vuetify components, but I meant custom components for my application.)
  • Using IndexedDB to store feed items for quicker access and offline support.

That was the plan, and like most plans, I wasn't necessarily able to hit everything in this update (and I'll explain why at the end). But hopefully you'll see the improvements as a general "moving in the right direction" for the application. With that out of the way, let's get started!

Implementing Vuex

I'll start off discussing the biggest change to the application, the addition of Vuex. As I said in the previous post, Vuex describes itself as a "state management pattern + library" on their "What is Vuex" page. No offense to their documentation, but I had a difficult time wrapping my head around exactly what this meant, from a practical sense.

After having using it in a few small projects now, I'm coming to appreciate what it provides. To me, the core benefit is providing a central interface to your data. If I've got a basic Vue app working with an array of values, I may have multiple different methods that modify it. What happens when I begin to have certain rules that must be applied before the data changes? As a simple example, imagine an array of RSS feeds. Before I add a new one, I want to ensure it doesn't already exist in the list. If I have one method that adds to the feed list, that isn't a problem, but if I have more, it may become cumbersome to keep that logic in sync across the different methods. I could simply build a utility to do this, but what happens when I have other components in play as well?

While it is absolutely not a one-to-one comparison, I feel like Vuex reminds me of how Providers or Services work in Angular. If I ever want to do work with any data, I'll ensure I use a central provider to handle all access to that data. That's how I look at Vuex.

So the big change in this application was to migrate all the data related items to a store. I began by adding the library to my HTML:

<script src="https://unpkg.com/vuex"></script>

Woot! Half-way done! (OK maybe not.)

I then created an instance of my store in my JavaScript file:

const feedStore = new Vuex.Store({ // lots of stuff here });

and included it in my Vue app:

let app = new Vue({ el: '#app', store:feedStore, // lots of stuff here too... });

Now comes the interesting part. Any time my Vue application needs data, which primarily consists of the list of feeds and the items from those feeds, it's going to ask the store for them. So, for example, my feeds value is now computed:

feeds() { return feedStore.state.feeds; },

This is now defined in the state portion of my store:

state: { allItems: [], feeds: [], selectedFeed: null },

Notice that feeds defaults to an empty array. I had previously used the created event of my Vue app to read in the data from localStorage. Now, I ask the store to do that:

created() { feedStore.dispatch('restoreFeeds'); },

Back in the store, the logic is pretty much the same:

restoreFeeds(context) { let feedsRaw = window.localStorage.getItem('feeds'); if(feedsRaw) { try { let feeds = JSON.parse(feedsRaw); context.state.feeds = feeds; context.state.feeds.forEach(f => { context.dispatch('loadFeed', f); }); } catch(e) { console.error('Error restoring feed json'+e); // bad json or other issue, nuke it window.localStorage.removeItem('feeds'); } } },

I say "pretty much the same" except now I'm doing a bit of error-checking on the value read in from localStorage. But here's the crucial bit. I already said I failed in terms of switching to IndexedDB, but in theory, I could build a third version of this application with an updated store and my Vue app won't know the difference. And that's where I started to get really excited. The more I worked, the more "dumb" my Vue app became and the less tied it was to any particular implementation of storage. Let's look at the complete Vue app now:

let app = new Vue({ el: '#app', store:feedStore, data() { return { drawer:true, addFeedDialog:false, addURL:'', urlError:false, urlRules:[], selectedFeed:null } }, computed: { showIntro() { return this.feeds.length == 0; }, feeds() { return feedStore.state.feeds; }, items() { return feedStore.getters.items; } }, created() { feedStore.dispatch('restoreFeeds'); }, methods:{ addFeed() { this.addFeedDialog = true; }, allFeeds() { feedStore.dispatch('filterFeed', null); }, addFeedAction() { this.urlError = false; this.urlRules = []; feedStore.dispatch('addFeed', {url:this.addURL}) .then(res => { this.addURL = ''; this.addFeedDialog = false; }) .catch(e =>{ console.log('err to add', e); this.urlError = true; this.urlRules = ["URL already exists."]; }); }, deleteFeed(feed) { feedStore.dispatch('deleteFeed', feed); }, filterFeed(feed) { feedStore.dispatch('filterFeed', feed); } } })

What you'll notice is that pretty much all of the actual logic is now gone and all I'm really doing here is UI stuff. Open a modal here, add an error there, and so forth.

You can view the complete store here, although I apologize for lumping everything together in one file.

Adding a Component

One of the other changes I mentioned was beginning to "component-ize" the view layer. I ended up only making one component, feed-item. This reduced the total number of lines in the HTML a bit:

<v-flex xs12 v-for="item in items" :key="item.link"> <feed-item :title="item.title" :content="item.content" :link="item.link" :feedtitle="item.feedTitle" :color="item.feedColor" :posted="item.pubDate"></feed-item> </v-flex>

It isn't a huge change by any means, but it did make it bit easier for me when I started working on the feed display. As I'm not using a fancy builder yet, I defined my component straight in JavaScript like so:

Vue.component('feed-item', { props:[ 'color','title','content','link','feedtitle', 'posted' ], template: ` <v-card :color="color"> <v-card-title primary-title> <div class="headline">{{title}} ({{posted | dtFormat}})</div> </v-card-title> <v-card-text> {{content | maxText }} </v-card-text> <v-card-actions> <v-btn flat target="_new" :href="link">Read on {{feedtitle}}</v-btn> </v-card-actions> </v-card> ` });

I'm not doing anything at all fancy in heremdash;there's no dynamic logic or events or anything like that, but I could certainly add that later where it makes sense. I did finally get around to adding the date and time of posting. If you're curious about how I built the formatter used for it, read my article Build A i18n Filter Using Vue.js & Native Web Specs."

The Power of Delete!

Oh, and I finally added a way to delete feeds:

Trash can icon, FTW!

This just fires off a method on the Vue object that, in turn, fires off a call to the store that takes care of removing the feed and items from the UI and then persisting it. A small thing, but, wow, did I wish I had that in the first version when testing. And here is a final shot of everything:

The awesome app in all it's awesomeness Next Steps... and What Happened to IndexedDB?

As I said in the beginning, this version is still not perfect but I definitely feel better about it. I highly encourage you to share tips, suggestions, and bug reports in the comments below or on the GitHub repo.

So what happened to IndexedDB support? The issue I ran into was how to properly initialize the database. Vuex stores don't have a concept of a created process. I could have done something like this:

// dummy code for getting feeds dispatch('getDB') .then(() => // do stuff );

Where the getDB action returns a promise and handles doing a one-time IndexedDB opening and storing the value in the state. I may give this a shot later, and again, what I love about Vuex is that I know I can safely do that without interfering with the rest of the application.

Article Series:
  1. Setup and first iteration
  2. Refinements and final version (This Post)

The post Building a RSS Viewer With Vue: Part 2 appeared first on CSS-Tricks.

Here’s the thing about “unused CSS” tools

Css Tricks - Mon, 06/18/2018 - 7:49am

There are a lot of tools that aim to help you remove "unused CSS" from your project. Never a week goes by that I don't see a tool for this being shared or promoted. It must strike some kind of perfect chord for some developers. I care about performance, and I know that reducing file sizes is good for performance. Indeed, it is. I bet we have CSS that is unused in our stylesheets, if we removed that, that's a performance win. Yep, it would be. We should automate that. Ehhhhhh, I'm not so sure.

There are major performance tooling players that play up this idea, like Lighthouse and how it gives you CSS and JS "Coverage", which will surely tell you that you're shipping code you don't need to be.

The tools that claim to help you with unused CSS have to perform analysis to be able to tell you what is unused and what isn't.

Here's one way to do that analysis. Render a page of your site and get the complete DOM. Then get the complete CSSOM as well, which can give you an array of all the selectors in your CSS. Loop over those selectors and do a querySelector in the DOM and see if it matches anything. If it doesn't, that CSS selector is unused.

Clever, right?!

I think so. But that analysis paints a rather limited picture.

Say that analysis runs two seconds after the page is complete, but there is some JavaScript that runs and injects a modal after five seconds (ughghk, I know). The analysis would have missed the HTML in that modal, which likely has styles, and thus would have incorrectly reported those styles as unused.

So, timing is one factor. Hopefully, this analysis tool has some way to configure multiple timings.

We're also only looking at one page so far. Of course, a site might have tens, hundreds, or thousands of pages. To be entirely sure about unused styles, looking at all of them is the most sure-fire bet.

Multiple pages is another factor. Hopefully, an analysis tool has a way to look at as many pages as you tell it to. Perhaps it can look at a sitemap?

Remember the timing thing? We might think of timing as one generic form of state. There are countless other things that could be state related. Is the user logged in or not? What plan are they on? Is their credit card expired thus showing some kind of special message? Do situational things like time/date/geolocation change state? What about real-time data? Stuff from an API?

Application-level state is clearly a big factor. Hopefully, this analysis tool can trigger/set all possible combinations of state.

There is interactive state as well. What about modals that come up because something is clicked? What is the active tab? Is this menu open or closed? What scroll position are they at? There are infinite permutations of this. Imagine a warning bar that shows up seven seconds after the user logs in to warn user about their expired credit card which contains a custom styled select menu which can be in an open or closed state, but only on the user settings page.

It seems unlikely that this analysis tool can handle all those possibilities. Even with loads of configuration, mock state, and integration testing, it couldn't cover the near-infinite possible permutations of all this.

And yet, I don't think these tools are useless — they are just...tools. Their use can actually be a positive step toward better code. Their use says OK, I admit it, I'm a little afraid our CSS. You could use this tool to get a broad picture of what your unused CSS might be, then combine that with your own knowledge of your CSS code base to make more informed decisions. Or take another technological step and do something like add a background image to those unused selectors and check server logs to see if they get hit.

It should be said that this whole idea of unused CSS is a part of the CSS-in-JS saga that our industry is going through. If all your styles are written as part of components, there kinda is no unused CSS. Either the component gets used and the styles come with it, or it doesn't. If you're particularly sensitive about the danger of unused CSS, that alone might sway you toward a CSS-in-JS tool.

It also should be said that this DOM and CSSOM analysis technique is only one possible way of checking for unused styles. If you had some kind of fancy tooling that could analyze all of your templates, styles, and scripts, presumably that could determine unused styles as well. We talk about that in the recent ShopTalk Show episode with Chris Eppstein.

The post Here’s the thing about “unused CSS” tools appeared first on CSS-Tricks.

Building a RSS Viewer With Vue: Part 1

Css Tricks - Mon, 06/18/2018 - 3:43am

As I explore, learn, and most importantly, play with Vue.js, I've been building different types of apps as a way to get practice with and improve my use of it. A few weeks ago, I was reading about the shut down of Digg's RSS Reader and while great alternatives exist, I thought it would be fun to build my own with Vue. In this article, I'm going to explain how I put it together and also what's wrong with it. I knew getting into this that I was going to make some compromises, so the plan is to follow up this version with a nicer one in a follow-up post.

Article Series:
  1. Setup and first iteration (This Post)
  2. Refinements and final version

Let's start by looking at the app and explaining the various components.

View DemoView Code A Look at the App

When opening the application, you're presented with some basic instructions and a prompt to add a new RSS feed.

Clicking the button opens a modal letting you enter a feed:

Once you add the button, the blog entries for that feed will be displayed:

Notice the color. I set it up so that each feed would have a unique color, making it easier to tell one site's content from another. For example, here is how it looks with more feeds added.

The panel on the left lets you filter by clicking on a feed. Unfortunately you can't delete a feed yet so, if you need to remove something, you'll need to open up your DevTools and edit the cached value.

Let's go over the tech stack!

The Components

First and foremost is the Vue library itself. I'm *not* using webpack for this application — just a simple script include with no build process.

The UI is all Vuetify, a very nice material design framework that is easy to use. I'm still learning it, so you can be sure that my design could be better, though I'm really happy with how it looks now.

Persistence is done via localStorage. I store the feed metadata retrieved from the RSS feed. This typically includes things like the name of the site, the main URL, and a description. I do not store feed items which means every time you load the site, I re-fetch items. The next version will keep items locally using IndexedDB.

So, how do I load feed information? I could just make a network request to the URL, but most RSS feeds aren't making use of CORS which means the browser would be blocked from loading it. To get around this, I wrote a quick serverless function with Webtask. It handles both creating a CORS-friendly endpoint as well as parsing the feeds’ XML into friendly JSON.

Now that I've covered the various parts of the application, let's start looking at the code!

The Layout

Let's start with the layout. As I said, I'm using Vuetify for the UI. I started off using the dark sample layout. This is what creates the header, footer, and left column used for the menu.

Application template

I used the card component for individual feed items. I'm not quite happy with the layout here. For example, I don't have publication dates rendered yet because I had trouble finding a nice way to render it. I decided to simply punt and wait till the next version, which we’ll **see in Part 2 of this series.

Instead of dumping the entire source code on you at once, let's look at the individual parts. First, here's the introductory/help text before any feeds have been added:

<div v-if="showIntro"> <p> Welcome to the RSS Reader, a simple way to manage RSS feeds and read content. To begin using the RSS Reader, add your first feed by clicking the button below. </p> <p> <v-btn color="primary" large @click="addFeed"> <v-icon>add</v-icon> Add Feed </v-btn> </p> </div>

When you do have feeds, items are displayed as a list of cards:

<v-container fluid grid-list-lg> <v-layout row wrap> <v-flex xs12 v-for="item in items"> <v-card :color="item.feedColor"> <v-card-title primary-title> <div class="headline">{{item.title}}</div> </v-card-title> <v-card-text> {{item.content | maxText }} </v-card-text> <v-card-actions> <v-btn flat target="_new" :href="item.link">Read on {{item.feedTitle}}</v-btn> </v-card-actions> </v-card> </v-flex> </v-layout> </v-container>

Note the button for reading a feed item uses a target to open it up in a new tab.

To display feeds, I use a list component:

<v-list dense> <v-list-tile @click="allFeeds"> <v-list-tile-action> <v-icon>dashboard</v-icon> </v-list-tile-action> <v-list-tile-content> <v-list-tile-title>All Feeds</v-list-tile-title> </v-list-tile-content> </v-list-tile> <v-list-tile @click="filterFeed(feed)" v-for="feed in feeds" :value="feed == selectedFeed"> <v-list-tile-action> <v-icon :color="feed.color">bookmark</v-icon> </v-list-tile-action> <v-list-tile-content> <v-list-tile-title>{{ feed.title }} </v-list-tile-title> </v-list-tile-content> </v-list-tile> <v-list-tile @click="addFeed"> <v-list-tile-action> <v-icon>add</v-icon> </v-list-tile-action> <v-list-tile-content> <v-list-tile-title>Add Feed</v-list-tile-title> </v-list-tile-content> </v-list-tile> </v-list>

Finally, here is the modal layout:

<v-dialog v-model="addFeedDialog" max-width="500px"> <v-card> <v-card-title>Add Feed</v-card-title> <v-card-text> Add the RSS URL for a feed below, or the URL for the site and I'll try to auto-discover the RSS feed. <v-text-field v-model="addURL" label="URL" :error="urlError" :rules="urlRules"></v-text-field> </v-card-text> <v-card-actions> <v-btn color="primary" @click.stop="addFeedAction">Add</v-btn> <v-btn color="primary" flat @click.stop="addFeedDialog=false">Close</v-btn> </v-card-actions> </v-card> </v-dialog> The Logic

Now for the fun part — JavaScript! As before, I'm not going to dump the entire file on you. Instead, let's tackle it bit by bit.

On start up, I load any existing feeds that may have defined and then display the introduction text, if needed:

created() { this.restoreFeeds(); if (this.feeds.length === 0) this.showIntro = true; },

The restoreFeeds method handles checking LocalStorage for existing feeds.

restoreFeeds() { let feeds = localStorage.getItem('feeds'); if (feeds) { this.feeds = JSON.parse(feeds); this.feeds.forEach((feed,idx) => { feed.color = colors[idx % (colors.length-1)]; this.loadFeed(feed); }); } },

Note that this method handles assigning a color (which is a simple array) and then loading feed data.

Speaking of that, how do I handle loading RSS information? Currently there are two times where this happens. First is when you initially add the feed and second when you reload the application and the feed was already defined. In both cases, I call one URL — the serverless task defined with Webtask. This task will return everything — the metadata about the feed and the items itself. I only care about the metadata on the *first* call and, in theory, I could have made the code a bit quicker by removing the metadata at the server side and strip that out but it didn't seem like it was worth the effort.

That serverless function is rather simple:

'use strict'; const Parser = require('rss-parser'); const parser = new Parser(); module.exports = function(context, cb) { let url = ''; if(context.body && context.body.url) url = context.body.url; if(context.query && context.query.url) url = context.query.url; if(url === '') cb(new Error('URL parameter not passed.')); console.log('gonna parse '+url); parser.parseURL(url) .then(feed => { console.log(feed); cb(null, {feed:feed}); }) .catch(e => { cb(e); }); }

All I'm doing here is wrapping the npm package rss-parser and that handles all the converting for me. The if statements you see in the beginning handle looking for the url parameter. When calling my webtask, I can either pass a query string variable or send it as part of a HTTP body. Either way, I simply use the rss-parser module and return the result.

The endpoint for this function is:

https://wt-c2bde7d7dfc8623f121b0eb5a7102930-0.sandbox.auth0-extend.com/getRss

You're welcome to try it out yourself. You can see this being used in the method handling adding a feed:

addFeedAction() { this.urlError = false; this.urlRules = []; //first, see if new if(this.feeds.findIndex((feed) => { return (feed.rsslink === this.addURL); }) >= 0) { this.urlError = true; this.urlRules = ["URL already exists."]; return; } else { fetch(rssAPI+encodeURIComponent(this.addURL)) .then(res => res.json()) .then(res => { // ok for now, assume no error, cuz awesome this.addURL = ''; //assign a color first res.feed.color = colors[this.feeds.length % (colors.length-1)]; // ok, add the items (but we append the url as a fk so we can filter later) res.feed.items.forEach(item => { item.feedPk = this.addURL; item.feedColor = res.feed.color; this.allItems.push(item); }); // delete items delete res.feed.items; // add the original rss link res.feed.rsslink = this.addURL; this.feeds.push(res.feed); this.addFeedDialog = false; //always hide intro this.showIntro = false; //persist the feed, but not the items this.storeFeeds(); }); } },

This method first checks if a feed already exists and, if it doesn't, it hits the serverless endpoint to get the details. I've got a bit of data duplication going on when I store items. I didn't want to store items "under" a feed object and instead use a global Vue data value, allItems. Therefore, I copy the feed identifier and color into each item. The idea was to make it easier to do item display and filtering later. This feels "wrong" to me, but again, this is my first draft. I'm using a computed property for items and you can see that logic here:

items:function() { if(this.allItems.length === 0) return []; // filter let items = []; if(this.selectedFeed) { console.log('filtered'); items = this.allItems.filter(item => { return item.feedPk == this.selectedFeed.rsslink; }); } else { items = this.allItems; } items = items.sort((a, b) => { return new Date(b.isoDate) - new Date(a.isoDate); }); return items; }

Looking at it now, I could gather my items from each feed instead of storing one global array, though I could address this later, if I want. I love that Vue gives me options for how to solve things like this.

Where Next?

When I started this article, I explicitly thought *this* *is* a first draft. I've pointed out things here and there that I like and don’t like, but what exactly do I plan for the next version?

  • I want to move all the data access into Vuex. Vuex is described as a "state management pattern + library" for Vue. If that doesn't make much sense to you, don't worry. I had no idea what it meant at first either. To me, Vuex provides a way to handle more complex data in an encapsulated manner. This becomes even more important as you start building more components that need to share data.
  • Speaking of components, I should consider making "item" a proper Vue component. That's an easy win.
  • I want to start storing feed items in IndexedDB so you'll get content the second you open the application. This will make the application much more performant and provide basic offline support. Of course, you can't read the full entries if you're offline, but at least *something* could be provided.
  • ...and anything you suggest! Take a look at the code and feel free to make suggestions and point out mistakes!

Stay tuned for the second post!

The post Building a RSS Viewer With Vue: Part 1 appeared first on CSS-Tricks.

Creating your own meme generator

Css Tricks - Fri, 06/15/2018 - 3:16am

Almost every time a new meme pops up in my Twitter feed, I think of a witty version to create. I'm not alone in this. Memes are often a way to acknowledge a shared experience or idea. In a variation of the "Is this a pigeon" meme that has been making the rounds online, a designer Daryl Ginn joked about the elementary nature of most applications that say they use artificial intelligence.

pic.twitter.com/nAHki0YFyV

— Daryl Ginn (@darylginn) May 16, 2018

Several people replied to his tweet saying something along the lines of "replace this with this." Daryl's version got them thinking about other possible variations. Platforms like imgFlip exist to make meme generations fast and easy. However, there is only so much customization they can allow. For many memes, creating new versions can only be done by people with Photoshop knowledge. But it doesn't have to be so! For some memes that require more than Impact for the font text on an image, a meme generator can be created using the HTML Canvas API. In this tutorial, we're going to make a generator for the #saltbae meme.

But first...

Let's look at some fun interactive meme examples!

The website pablo.life allows you to create your own Kanye West TLOP album cover by changing the text and image.

This is one of my favorites:

The digital agency R/GA created the Straight Outta Somewhere campaign where users "show the world where they're from by uploading their own photo and filling in the blank after 'Straight Outta ____.'" Users can download and share the meme.

Developer Isaac Hepworth created the Trump Executive Order Generator.

Spotify collaborated with Migos to create a range of downloadable Valentine's Day cards that can be customized by changing names.

Let's build our own meme generator!

Now, the tutorial. In a popular version of the #saltbae meme, instead of salt, Salt Bae (whose name is Nusret Gökçe) sprinkles something other than salt.

Loading an image

The first thing we have to do is load the original image onto the canvas. You can load an image one of two ways: from a URL or from one that exists in the DOM using the <img> tag but is hidden.

Here's how we do it with a hidden image tag:

<canvas id="canvas" width="1024" height="1024"> Canvas requires a browser that supports HTML5. </canvas> <img crossOrigin="Anonymous" id="salt-bae" src="http://res.cloudinary.com/dlwnmz6lr/image/upload/v1520011253/170203-salt-bae-mn-1530_060e5898cdcf7b58f97126d3cfbfdf71.nbcnews-ux-2880-1000_kllh1d.jpg"/>

I'm hosting the image on Cloudinary and added the crossOrigin attribute so we don't run into any CORS issues.

function drawImage(text) { const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); ctx.clearRect(0, 0, canvas.width, canvas.height); const img = document.getElementById('salt-bae'); ctx.drawImage(img, 0, 0, canvas.width, canvas.height); } window.onload = function() { drawImage(); }

We're using the canvas drawImage function to draw the image to the canvas. It can be used to draw videos or parts of an image as well. The method provides different ways to do this. We're drawing the image by indicating the position and the width and height of the image.

ctx.drawImage(img, x, y, width, height);

Alternatively, we could load the image from a URL:

function loadAndDrawImage(src) { // Create an image object. (Not part of the dom) const image = new Image(); // After the image has loaded, draw it to the canvas image.onload = () => { // draw image }; // Then set the source of the image that we want to load image.src = src; }

Now we load in an image to replace the sprinkles Salt Bae is throwing. First, we load the image using one of the techniques I mentioned earlier, then we draw it to the screen like we did with the Salt Bae base image.

function getRandomInt(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive } function drawBackgroundImage(canvas, ctx) { ctx.clearRect(0, 0, canvas.width, canvas.height); const img = document.getElementById('salt-bae'); ctx.drawImage(img, 0, 0, canvas.width, canvas.height); } function getRandomImageSize(min, max, width, height) { const ratio = width / height; // Used for aspect ratio width = getRandomInt(min, max); height = width / ratio; return { width, height }; } function drawSalt(src, canvas, ctx) { // Create an image object. (Not part of the dom) const image = new Image(); image.src = src; // After the image has loaded, draw it to the canvas image.onload = function() { for (let i = 0; i < 8; i++) { const randomX = getRandomInt(10, canvas.width/2); const randomY = getRandomInt(canvas.height-300, canvas.height); const dimensions = getRandomImageSize(20, 100, image.width, image.height); ctx.drawImage(image, randomX, randomY, dimensions.width, dimensions.height); } } return image; } onload = function() { const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); drawBackgroundImage(canvas, ctx); const saltImage = drawSalt('http://res.cloudinary.com/dlwnmz6lr/image/upload/v1526005050/chadwick-boseman-inspired-workout-program-wide_phczey.webp', canvas, ctx); };

Now we can let users sprinkle something other than sprinkles.

Uploading an image

We're going to add a button that triggers an image upload and includes an event listener to listen for a change.

<input type="file" class="upload-image">` function updateImage(file, img){ img.src = URL.createObjectURL(file); } onload = function() { const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); drawBackgroundImage(canvas, ctx); const saltImage = drawSalt('http://res.cloudinary.com/dlwnmz6lr/image/upload/v1526005050/chadwick-boseman-inspired-workout-program-wide_phczey.webp', canvas, ctx); const input = document.querySelector("input[type='file']"); /* * Add event listener to the input to listen for changes to its selected * value, i.e when files are selected */ input.addEventListener('change', function() { drawBackgroundImage(canvas, ctx); // clear canvas and re-draw updateImage(this.files[0], saltImage); }); };

URL.createObjectURL() creates a DOMString containing a URL representing the object given in the parameter which, in this case, is the uploaded file.

We can even up the game a little bit, like providing some default options. I've added a few emojis you can play around with as a starting point.

Downloading the final image

Once the new meme has been generated, we want users to be able to download and share it. The typical way of doing this is by opening the canvas in a new tab using the toDataURL method but the user would have to right click to save the image from that tab and that's not very convenient.

So, instead, we can take advantage of the download attribute added to links in HTML5. We create a link that, on click, sets the download attribute to the result of canvas.toDataURL. The toDataURL() method "returns a data URI containing a representation of the image in the format specified."

function addLink() { var link = document.createElement('a'); link.innerHTML = 'Download!'; link.addEventListener('click', function(e) { link.href = canvas.toDataURL(); link.download = "salt-bae.png"; }, false); link.className = "instruction"; document.querySelectorAll('section')[1].appendChild(link); }

Well that's it! Our meme generator is done.

Some cool links
  • Darius Kazemi has been making a bunch of twitter bots that generate memes.
  • Vox Media has a meme generator called meme that's open source.

Meme away!

The post Creating your own meme generator appeared first on CSS-Tricks.

More Unicode Patterns

Css Tricks - Thu, 06/14/2018 - 3:56am

Creating is the most intense excitement one can come to know.

Anni Albers, On Designing

I recently wrote a post — that was shared here on CSS-Tricks — where I looked at ways to use Unicode characters to create interesting (and random) patterns. Since then, I’ve continued to seek new characters to build new patterns. I even borrowed a book about Unicode from a local library.

(That's a really thick book, by the way.)

It's all up to your imagination to see the possible patterns a Unicode character can make. Although not all characters are good as patterns, the process is a good exercise for me.

And, aside from Unicode itself, the methods to build the patterns may not be so obvious. It usually takes a lot of inspiration and trial and error to come up with new ones.

More tiling

There are actually many ways to do tiling. Here’s one of my favorite tile patterns, which can be easily achieved using CSS grid:

.grid { /* using `dense` to fill gaps automatically. */ grid-auto-flow: dense; } .cell { /* using `span` to change cell size */ grid-column-end: span <num>; grid-row-end: span <num>; }

Grid Invaders by Miriam Suzanne is a good example of this technique.

Now, what I'm trying to do is put some Unicode characters into this grid. And most importantly, update the font-size value according to the span of its cell.

Pattern using characters \2f3c through \2f9f

I only tested with Chrome on Mac. Some of the examples may look awful on other browsers/platforms.

.cell { /* ... */ --n: <random-span>; grid-column-end: span var(--n); grid-row-end: span var(--n); } .cell:after { /* ... */ font-size: calc(var(--n) * 2vmin); }

It's a bit like the Tag Cloud effect, but with CSS. Lots of patterns can be made this way.

Pattern using characters \2686 through \2689 Pattern using charaters \21b0, \21b1, \21b2 and \21b4

The span of the columns and rows don't always have to be the same value. We can make small modifications by changing how many rows each cell spans:

.cell { /* only change the row span */ grid-row-end: span <num>; }

Since the font-size property scales up/down in both directions (vertically and horizontally), the scaleY() in the transform property will be used instead.

Pattern using characters \25c6 through \25c8 :after { /* ... */ transform: scaleY(calc(var(--span) * 1.4)); }

And here's another one, made by rotating the inner container of the grid to some degree.

The triangles also can be drawn with clip-path and will be more responsive, but it's nice to do something in a different way.

More modifications to the layout:

.column-odd { transform: skewY(40deg); } .column-even { transform: skewY(-40deg); }

Now follow these transformations for each column.

Pattern using characters \1690 through \1694 Composition

Many Unicode pairs share some kind of shape with different angles. For example, parentheses, brackets, and arrows with different that go in different directions. We can use this concept to combine the shapes and generate repeatable patterns.

This pattern uses less-than and greater-than signs for the base:

< and >" /> :nth-child(odd):after { content: '<'; } :nth-child(even):after { content: '>'; }

Here we go with parentheses:

A wavy pattern using ( and ) :nth-child(odd):after { content: '('; } :nth-child(even):after { content: ')'; }

These are characters we use everyday. However, they give us a fresh look and feeling when they are arranged in a new way.

There's another pair of characters, ?, and ?. Placing them in the grid and scaling to a proper value connect them together into a seamless pattern:

It's like weaving with characters! We can even take it up a notch by rotating things:

Pattern using \169b and \169c Rings

Last week, I joined a CodePen Challenge that challenged the group to make a design out of the sub and sup elements. As I experimented with them, I noticed that the two tags scaled down automatically when nested.

So, I tried to put them around a circle:

.first-level { /* Slice the circle into many segments. */ transform: rotate( calc(360deg / var(--slice) * var(--n)) ); }

Suddenly, I realized this method can be used to generate background patterns, too. The results are pretty nice.

Pattern using \003e sub:after, sup:after { content: '\003e'; }

The interesting thing is that changing a single character can end up with very different results.

Combining \002e and \003e together to form a pattern Combining \25c9 and \2234 creates a different effect in the same circular layout Wrapping up

That's all for now! The color palettes used in this article are from Color Hunt and Coolors.co.

The examples are generated with css-doodle, except for Ring examples in the last section. Everything here can be found in this CodePen collection.

Hope you like them and thanks for reading!

The post More Unicode Patterns appeared first on CSS-Tricks.

?Truly understand your site visitors’ behavior

Css Tricks - Thu, 06/14/2018 - 2:51am

(This is a sponsored post.)

Hotjar is a quick and easy way to truly understand your visitors and identify opportunities for improvement and growth.

Try the all-in-one analytics and feedback tool for free.

Direct Link to ArticlePermalink

The post ?Truly understand your site visitors’ behavior appeared first on CSS-Tricks.

UX Case Study: Spotify Vs. Apple Music Mobile Apps

Usability Geek - Wed, 06/13/2018 - 12:47pm
And we are back in action! It has been awhile since our last UX Case Study so that I will give a brief refresher for our returning readers and an intro for the uninitiated. *Ahem*. In a blogosphere...
Categories: Web Standards

Understanding the Almighty Reducer

Css Tricks - Wed, 06/13/2018 - 4:34am

I was recently mentoring someone who had trouble with the .reduce() method in JavaScript. Namely, how you get from this:

const nums = [1, 2, 3] let value = 0 for (let i = 0; i < nums.length; i++) { value += nums[i] }

...to this:

const nums = [1, 2, 3] const value = nums.reduce((ac, next) => ac + next, 0)

They are functionally equivalent and they both sum up all the numbers in the array, but there is a bit of paradigm shift between them. Let's explore reducers for a moment because they're powerful, and important to have in your programming toolbox. There are literally hundreds of other articles on reducers out there, and I'll link up some of my favorites at the end.

What is a reducer?

The first and most important thing to understand about a reducer is that it will always only return one value. The job of a reducer is to reduce. That one value can be a number, a string, an array or an object, but it will always only be one. Reducers are really great for a lot of things, but they're especially useful for applying a bit of logic to a group of values and ending up with another single result.

That's the other thing to mention: reducers will not, by their nature, mutate your initial value; rather they return something else. Let's walk over that first example so you can see what's happening here. The video below explains:

Your browser does not support the video tag.

It might be helpful to watch the video to see how the progression occurs, but here's the code we're looking at:

const nums = [1, 2, 3] let value = 0 for (let i = 0; i < nums.length; i++) { value += nums[i] }

We have our array (1, 2, 3) and the first value each number in the array will be added to (0). We walk through the amount of the array and add them to the initial value.

Let's try this a little differently:

const nums = [1, 2, 3] const initialValue = 0 const reducer = function (acc, item) { return acc + item } const total = nums.reduce(reducer, initialValue)

Now we have the same array, but this time we're not mutating that first value. Instead, we have an initialValue that will only be used at the start. Next, we can make a function that takes an accumulator ?and an item. The accumulator is the collected value? returned in the last invocation that informs the function what the next value will be added to. In this case of addition, you can think of it as a snowball rolling down a mountain that eats up each value in its path as it grows in size by every eaten value.

We’ll use .reduce() to apply the function and start from that initial value. This can be shortened with an arrow function:

const nums = [1, 2, 3] const initialValue = 0 const reducer = (acc, item) => { return acc + item } const total = nums.reduce(reducer, initialValue)

And then shortened some more! Implicit returns for the win!

const nums = [1, 2, 3] const initialValue = 0 const reducer = (acc, item) => acc + item const total = nums.reduce(reducer, initialValue)

Now we can apply the function right where we called it, and we can also plop that initial value directly in there!

const nums = [1, 2, 3] const total = nums.reduce((acc, item) => acc + item,

An accumulator can be an intimidating term, so you can think of it like the current state of the array as we're applying the logic on the callback's invocations.

The Call Stack

In case it's not clear what's happening, let's log out what's going on for each iteration. The reduce is using a callback function that will run for each item in the array. IThe following demo will help to make this more clear. I've also used a different array ([1, 3, 6]) because having the numbers be the same as the index could be confusing.

See the Pen showing acc, item, return by Sarah Drasner (@sdras) on CodePen.

When we run this, we'll see this output in the console:

"Acc: 0, Item: 1, Return value: 1" "Acc: 1, Item: 3, Return value: 4" "Acc: 4, Item: 6, Return value: 10"

Here's a more visual breakdown:

Your browser does not support the video tag.

  1. It shows that the accumulator is starting at our initial value, 0
  2. Then we have the first item, which is 1, so our return value is 1 (0 + 1 = 1)
  3. 1 becomes the accumulator on the next invocation
  4. Now we have 1 as the accumulator and 3 is the item aince it is next in the array.
  5. The returned value becomes 4 (1 + 3 = 4)
  6. That, in turn, becomes the accumulator and the next item at invocation is 6
  7. That results in 10 (4 + 6 = 10) and is our final value since 6 is the last number in the array
Simple Examples

Now that we've got that under our belt, let's look at some common and useful things reducers can do.

How many of X do we have?

Let's say you have an array of numbers and you want to return an object that reports the number of times those numbers occur in the array. Note that this could just as easily apply to strings.

const nums = [3, 5, 6, 82, 1, 4, 3, 5, 82] const result = nums.reduce((tally, amt) => { tally[amt] ? tally[amt]++ : tally[amt] = 1 return tally }, {}) console.log(result)

See the Pen simplified reduce by Sarah Drasner (@sdras) on CodePen.

Wait, what did we just do?

Initially, we have an array and the object we’re going to put its contents into. In our reducer, we ask: does this item exist? If so, let's increment it. If not, add it and set it to 1. At the end, please return the tally count of each item. Then, we run the reduce function, passing in both the reducer and the initial value.

Take an array and turn it into an object that shows some conditions

Let’s say we have an array and we want to create an object based on a set of conditions. Reduce can be great for this! Here, we want to create an object out of any instance of a number contained in the array and show both an odd and even version of this number. If the number is already even or odd, then that’s what we’ll have in the object.

const nums = [3, 5, 6, 82, 1, 4, 3, 5, 82] // we're going to make an object from an even and odd // version of each instance of a number const result = nums.reduce((acc, item) => { acc[item] = { odd: item % 2 ? item : item - 1, even: item % 2 ? item + 1 : item } return acc }, {}) console.log(result)

See the Pen simplified reduce by Sarah Drasner (@sdras) on CodePen.

This will shoot out the following output in the console:

1:{odd: 1, even: 2} 3:{odd: 3, even: 4} 4:{odd: 3, even: 4} 5:{odd: 5, even: 6} 6:{odd: 5, even: 6} 82:{odd: 81, even: 82}

OK, so what's happening?

As we’re going through every item in the array, we create a property for even and odd, and based on an inline condition with a modulus operator, we’ll either store the number or increment it by 1. The modulus operator is really good for this because it can quickly check for even or odd — if it's divisible by two, it's even, if not, it's odd.

Other resources

At the top, I mentioned other posts out there that are handy resources to get more familiar with the role of reducers. Here are a few of my favorites:

  • The MDN documentation is wonderful for this. Seriously, it's one of their best posts, IMO. They also describe in a bit more detail what happens if you don't provide an initial value, which we didn't cover in this post.
  • Daniel Shiffman is always amazing at explaining things on Coding Train.
  • A Drip of JavaScript does a good job, too.

The post Understanding the Almighty Reducer appeared first on CSS-Tricks.

Your Brain on Front-End Development

Css Tricks - Wed, 06/13/2018 - 3:59am

Part of the job of being a front-end developer is applying different techniques and technologies to pull off the desired UI and UX. Perhaps you work with a design team and implement their designs. I know when I look at a design (heck, even if I know I'm not going to be building it), my front-end brain starts triggering all sorts of things I know will be related to the task.

Let's take a look at what I mean.

Check out this lovely Dribbble shot for a Food Recipe Website from Riko Sapto Dimo.

It's a very appealing design, and there is loads in there to think about from a front-end web design and development standpoint.

We're going to mostly be talking about design pattern choices and HTML/CSS tech choices. There is much more to the job of front-end development. Accessibility! Performance! Semantics! Design systems! All important stuff as well.

Multi-line padded text

Ah yes, that look where text has a background that follows the length of the lines of text. We've called that Multi-Line Padded Text in the past and looked at a number of ways to do it. The easiest and most modern way to handle it is with box-decoration-break.

See the Pen Multiline Padding with box-decoration-break by Chris Coyier (@chriscoyier) on CodePen.

Flexbox header

That header area is just begging for flexbox. It's a single-direction layout with elements of different sizes and different space between them. Expressing that in flexbox is going to be easier than any other method and not require any fixed sizing or magic numbers — not to mention flexible!

Grid layout

The overall page layout here could be expressed nicely with CSS grid. Remember that flexbox and grid are not at odds. An element placed in a grid cell can be flexbox! Like the header above, that makes perfect sense. The main content area and footer, as grid cells, could probably go either way.

Vertical writing

Not the most obvious thing to pull off! Your best bet is using writing modes. Jen Simmons has written about this, and here's a demo:

See the Pen Writing Mode Demo — Headline by Jen Simmons (@jensimmons) on CodePen.

Line clamping

Looks like we have some truncation going on here. General performance-wise, we'd probably be wanting the data being sent only be a few lines long. But the front end can help with this too, if it has to. Three lines of text are shown here with ellipsis at the end. Perhaps the design really needs the copy to always be a maximum of three lines. That's called line clamping.

See the Pen Line Clampin' by Chris Coyier (@chriscoyier) on CodePen.

Custom fonts

Like most sites these days, this design is coated in custom web fonts. With a design this striking, I'd be very careful about my font loading technique. My gut tells me I'd be more into FOIT than FOUT here, and ideally I'd cache that font file as hard as I could so that we'd have neither as often as possible.

Text over images

That text "Dinner Menu" is squarely over some busy photographic imagery below. It's still readable though, largely because of the bright white of the text over a darkened image. We've covered thinking this through in the past in detail. White text over a darkened image is generally the way to go, and darkened enough such that just about any image will be OK. There are other options though, like gradients and blurring (which is also in use here in the footer)

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

SVG icons / Star ratings

There are a number of simple, vector icons scattered around the design. Those are a sure-bet for an SVG icon system. This is my current recommendation for approaching an SVG icon system. Inline the SVG. Simple and powerful.

Those star ratings are probably SVG territory as well. Here's a good collection of options. Progressively enhancing from radio buttons always seems like a smart way to go:

See the Pen CSS: Radio Input Stars by Jake Albaugh (@jakealbaugh) on CodePen.

Hamburgers

It might seem a little superfluous on a large screen design like this, especially as there is navigation already visible. But hey, it's hard to avoid these days and there is something to be said about training users where site navigation can happen regardless of where you're looking at the site.

Here's a collection of those type of menus.

See the Pen Hamburger menu flip with text change by Eric Grucza (@egrucza) on CodePen.

Anything else in the design I didn't mention that your mind goes to right away?

The post Your Brain on Front-End Development appeared first on CSS-Tricks.

A Quick Roundup of Recent React Chatter

Css Tricks - Tue, 06/12/2018 - 7:37am

Like many, many others, I'm in the pool of leveling up my JavaScript skills and learning how to put React to use. That's why Brad Frost resonated with me when he posted My Struggle to Learn React."

As Brad does, he clearly outlines his struggles point-by-point:

  • I have invested enough time learning it
  • React and ES6 travel together
  • Syntax and conventions
  • Getting lost in this-land
  • I haven’t found sample projects or tutorials that match how i tend to work
  • I'm less competent at JS than HTML and CSS

It seems that Brad's struggles resonated with others as well, inspiring empathy and help from the community. For example, Kevin Ball touches on the second and third frustrations by supplying a distinction between React and ES6 and examples of the syntax and conventions of each:

For each feature, I show a couple examples of what it might look like, identify where it is coming from, give you a quick overview of what is called and what it does, and link off to some resources that can help you learn about it.

Super awesome!

Shortly following Brad's post was this tweet from Sara Soueidan:

I’m just gonna throw this bomb here:

React is the new jQuery

There you go.

— Sara Soueidan (@SaraSoueidan) May 24, 2018

You know that lit up the Twitterverse. Yes, it's provocative, but the sentiment is pretty clean cut as she clarified a little later:

I used to LOVE jQuery, but hated how it was overused even when it was completely unneeded and unnecessary and, dare I say, sometimes harmful.

I hope this clarifies my controversial tweet from this afternoon. ;)

— Sara Soueidan (@SaraSoueidan) May 24, 2018

Speaking of jQuery, Sarah Drasner had written a post a little while ago that showed how Vue can be used as a jQuery replacement and requires no build process at all. Well, the same can be true of React, despite the fact that both frameworks are predominantly used in complex app environments.

And, if all this talk about moving away from jQuery and into complex app environments sounds scary, then maybe this interview with Bruce Lawson will be reassuring to you. After all:

The end user doesn't care whether your website is made with React or Angular or webpack or Broccoli or Grunt or whatever. They just want it to work in their damn browser.

But, still, there may be circumstances where React will be the right tool for the job and you'll want it in your toolbox. For example, WordPress is using it as the basis for it's upcoming Gutenberg editor meaning WordPress developers (and that's a lot of us) will want to heed Matt Mullenweg's advice to "learn JavaScript deeply." Our guide on developing for Gutenberg might be a great place for you to start that journey.

All in a day's work, right?!

The post A Quick Roundup of Recent React Chatter appeared first on CSS-Tricks.

Linkbait 41

QuirksBlog - Tue, 06/12/2018 - 5:28am

Friends edition. Lots of articles by people I’ve known for ages. Not sure why; probably just a coincidence.

  • The Big Z deplores the cult of the complex.

    in a field where young straight white dudes take an overwhelming majority of the jobs (including most of the management jobs) it’s perhaps to be expected that web making has lately become something of a dick measuring competition.

    Before you diss him (and me) as an old fart who isn’t keeping up with the times, please consider the following question: At which time can we start to safely say that people who just cram frameworks into everything they make are too set in their ways and can’t keep up with the latest trends? Two years? Three? Five?
  • Brad takes a middle position between those who applaud the shiny new and those who deplore it, by asking (rather testily? or is that just my imagination?) why both sides treat a simple “I don’t understand X” as fodder for their view of web development. (I am guilty as charged, I’m afraid.)
  • Jeremy hopes AMP will drive itself to extinction.

    If anything, I’ve noticed publishers using the existence of their AMP pages as a justification for just letting their “regular” pages put on weight.

    and

    I wish that AMP were being marketed more like a temporary polyfill. And as with any polyfill, I look forward to the day when AMP is no longer necesssary.

  • Rachel wrote a massive guide to CSS layout. I’ll have to study it closely if I ever write the CSS book for JavaScripters. I did not know about display: flow-root.
  • Ethan is a little excited about Safari (or, at least, WebKit) coming to the Apple Watch. So am I. It’ll be interesting to see how they solved the low-memory and small-screen issues. Ethan’s article contains a lot of useful links.
  • I’m not excited about yet another meta tag, though — see Erik Runyon’s article for the details. I wish we could have left it at the existing one, but of course web designers didn’t make their old sites fit for 272px, which appears to be the ideal layout viewport width of the smallest watch.
  • Tim adds some performance notes:

    The median site sends about 351kb of compressed JavaScript to “mobile” devices according to HTTP Archive. That’s roughly 1.7-2.4MB of uncompressed JavaScript the browser has to parse, compile, and execute. That little S3 processor is going to struggle if we try to serve anything close to the amount of JavaScript that we serve to everything else.

    Use AMP? (Just kidding)
    We can hope that this will drastically drop average JS usage, but it probably won’t.
  • The inimitable Lin Clark wrote cartoon introductions to DNS over HTTPS and ES modules.
  • A very useful overview of current VR sets, including their browsers and WebVR support.
  • Speaking of which, Tesla updated its browser. It’s not a cutting-edge one, judging by the HTML5 Tests screenshots, but I can see why disabling video in a car browser might be a good idea.
  • Have a tip for the next Linkbait? Or a comment on this one? Let me know (or here or here).

Creating a Bar Graph with CSS Grid

Css Tricks - Tue, 06/12/2018 - 4:21am

If you’re looking for more manageable ways to create bar graphs, or in search of use cases to practice CSS Grid layout, I got you!

Before we begin working on the graph, I want to talk about coding the bars, when Grid is a good approach for graphs, and we’ll also cover some code choices you might consider before getting started.

Preface

The bar is a pretty basic shape: you can control its dimensions with CSS width, height, number of grid or table cells, etc. depending on how you’ve coded it. As far as graphs go, the main thing we want to control is the height of the bars in the graph.

Controlling height with Grid cells (like here) is convenient for designs where the height is incremental by a fixed value — no in-betweens. For example, signal bars in phones or when you don’t mind setting a lot of grid rows to better control the bar height down to its smallest value, like IRL graph paper.

For my graph, I want gradient bars as well as vertical and horizontal axes labels. So, to make it easy, I have decided to control the bar height with gradient sizing, and determine the number of grid rows based on the number of vertical axis labels I want.

Also, other than the contents for the graph — bars, axes labels, and captions — there’ll be no data present in the HTML, like data about bar colors and dimensions.

data-* attributes are used to provide that sort of information in HTML. But I didn’t want to switch back and forth between HTML and CSS while coding, and decided to completely separate the content from the design. It’s totally up to you. If you feel like using data-* might benefit your project, go for it.

I’ve created a diagram below that you might find useful to refer to while reading the code. It depicts the graph and the grid that contains it. The numbers represent grid lines.

Let’s code this thing.

The HTML

Grid can automatically place items in top-bottom and left-right directions. To take advantage of that, I’m going to add the graph contents in the order y-axis labels (top-bottom), bars, and x-axis labels (left-right). This way, I only need to write the HTML markup and the CSS will place the bars for me!

<figure aria-hidden="true"> <div class="graph"> <span class="graphRowLabel">100</span> <span class="graphRowLabel">90</span> <span class="graphRowLabel">80</span> <span class="graphRowLabel">70</span> <span class="graphRowLabel">60</span> <span class="graphRowLabel">50</span> <span class="graphRowLabel">40</span> <span class="graphRowLabel">30</span> <span class="graphRowLabel">20</span> <span class="graphRowLabel">10</span> <div class="graphBar"></div> <div class="graphBar"></div> <div class="graphBar"></div> <div class="graphBar"></div> <div class="graphBar"></div> <span><sup>Y </sup>&frasl;<sub> X</sub></span> <span class="graphColumnLabel">&#x1f60a;</span> <span class="graphColumnLabel">&#x1f604;</span> <span class="graphColumnLabel">&#x263a;&#xfe0f;</span> <span class="graphColumnLabel">&#x1f601;</span> <span class="graphColumnLabel">&#x1f600;</span> </div> <figcaption>Made with CSS Grid &#x1f49b;</figcaption> </figure> <span class="screenreader-text">Smiling face with squinting eyes: 10%, grinning face with squinting eyes: 65%, smiling face: 52%, grinning face with smiling eyes: 100%, and grinning face: 92%.</span>

Note: If you’re interested in accessibility, know that I’m not an accessibility expert. But when I tried to make the bars accessible, screen reader experience simply sucked. Using aria-labelledby wasn’t that good either. So, I added a text description of the graph and hid it from the visual display. That made the reading much more natural.

The CSS

This is where the magic happens.

/* The grid container */ .graph { display: grid; grid: repeat(10, auto) max-content / max-content repeat(5, auto); /* ... */ }

We’ve defined eleven rows and six columns in our grid with these two little lines of CSS: ten automatically sized rows and one sized to its "maximum content"; one column sized to its "maximum content" and five automatically sized. CSS Grid is a beautiful thing.

The graph bars need to cover the grid from the first row to the second-to-last row since we are using the last one for the x-axis labels. I gave the bars 100% height, and grid-row: 1 / -2; which means "span the items from first horizontal grid line till the second last."

/* A grid item */ .graphBar{ height: 100%; grid-row: 1 / -2; }

The bars also have linear gradient going upwards. The size of the colored portion of the gradient is the indicator of bar’s height, which in turn is taken from each bar’s own CSS rule as a custom variable.

/* A grid item */ .graphBar{ /* Same as before */ background: palegoldenrod linear-gradient(to top, gold var(--h), transparent var(--h)); }

To control the width of the bars and the space between them, I use a fixed width and centered them with justify-self: center;. You can instead use grid-column-gap to create gaps between columns if you want. Here’ the full code that pulls everything for the bars together:

/* A grid item */ .graphBar{ height: 100%; grid-row: 1 / -2; background: palegoldenrod linear-gradient(to top, gold var(--h), transparent var(--h)); width: 45px; justify-self: center; }

Did you notice the CSS variable (var(--h)) in there? We need to specify the exact height of each bar and we can use the variable to determine the height of the background gradient in terms of percentage:

.graphBar:nth-of-type(1) { grid-column: 2; --h: 10%; } .graphBar:nth-of-type(2) { grid-column: 3; --h: 65%; } .graphBar:nth-of-type(3) { grid-column: 4; --h: 52%; } /* and so on... */

That’s it! after styling, the graph looks like this:

See the Pen CSS Bar Graph with Grid by Preethi (@rpsthecoder) on CodePen.

There are a few demo-specific styles in here but everything we’ve covered so far will get you the basic framework for a bar graph. The y-axis labels I created are positioned on top of the grid lines for a slightly cleaner layout. I got the cylindrical shape and the cross-section edges of the bars by using border-radius and elliptic pseudo elements, respectively. Without them, you’ll get a straight up rectangular bar.

The post Creating a Bar Graph with CSS Grid appeared first on CSS-Tricks.

??Build live comments with sentiment analysis using Nest.js

Css Tricks - Tue, 06/12/2018 - 4:18am

(This is a sponsored post.)

Interestingly, one of the most important areas of a blog post is the comment section. This plays an important role in the success of a post or an article, as it allows proper interaction and participation from readers. This makes it inevitable for every platform with a direct comments system to handle it in realtime.

In this post, we’ll build an application with a live comment feature. This will happen in realtime as we will tap into the infrastructure made available by Pusher Channels. We will also use the sentiment analysis to measure whether comments are positive or negative, and display this information on an admin panel.

Direct Link to ArticlePermalink

The post ??Build live comments with sentiment analysis using Nest.js appeared first on CSS-Tricks.

Versioning Interview

Css Tricks - Mon, 06/11/2018 - 7:45am

Adam Roberts (who you might recognize from our interview with him), interviewed me for the Versioning newsletter. I'm publishing my answers here for y'alls perusal as well!

Which dev/tech idea or trend excites you the most at the moment, and why?

I love that new JavaScript has arrived. I don’t know if "new JavaScript" is really the word for it, but that’s what it feels like. Major syntax improvements coupled with state and component-based thinking, coupled with powerful frameworks tying it all together: React, Angular, Vue, Ember, etc. Plus the ecosystem they live in, which often includes ES6+ processing, building/bundling, state management tools, and more.

Particularly impressive are tools like Create React App that get you cooking on a whole fancy setup like that in seconds. Vue CLI is similarly amazing.

Combined with serverless / JAMstack stuff, I love it all the more.

This stuff is so thick in the air right now it’s definitely not going away, like it or not. It will evolve, but this whole thing that I call New JavaScript (for lack of a better overall term) is gonna be around for a hot while.

Which dev/tech idea or trend is overrated, and why?

I’d hate to crap on any particular idea. For one, I’m not sure it does anybody any good. But also, I’m so often wrong about stuff like this. It reminds me of my track record guessing if a startup is a good idea or not. It seems like if I find myself rolling my eyes at a startup it will get huge, and if I think it’s absolutely amazing it’ll be dead in a year.

Describe (or link to!) something cool you built, designed or produced recently. Why is it cool, why are you proud of it?

Just recently I built a little microsite about Serverless technology. I’m far from an expert, but that’s part of why it’s cool in a way. It’s what I’ve been doing my whole career. I’m a beginner about this Serverless stuff, and that’s sometimes when it’s the best time to write about something, because your empathy is at a maximum for other people that don’t get it.

The point of the site is explaining why serverless is useful even for front-end developers, all the zillion services that are a part of the serverless world, plus ideas and resources.

How did you build it?

Using CodePen! It’s a static site (Of course! Serverless!), but I still wanted to work in a componentized way. That ended up being perfect for Nunjucks, which is a technology we support on CodePen Projects. I wrote about the whole process on Smashing Magazine.

How did you find yourself interested in this stuff?

One thing that happened is that we jumped on some serverless technology at CodePen. We have some pretty perfect use cases for serverless functions, like using them for preprocessing. For us, they are fast, easy to set up, easy to maintain and less expensive than spinning up our own servers. Not to mention less expensive.

I’m no expert though. I just think it’s fascinating to watch as someone who likes to watch what’s happening in our industry. It’s part of my job too, really, as I write and talk about the web pretty regularly. One reason I’m excited about them is because a front-end developer with some JavaScript skills can take advantage of them to do things they might not even realize they can do. That’s kind of a big deal!

Joining the dots between the component-based thinking and serverless tech, has this changed how you think people should develop a project?

I’m always hesitant to tell people how to build their stuff. Although I probably don’t do as good a job at that as I want to. I think a better tone is to explain what works for you and why and let people digest that how they will.

Some trends are impossible to ignore though. Component-based thinking is likely here to stay. It seems like one of those ideas that is just a result of our industry maturing into patterns that help everyone. Plus it’s abstract enough that the concept lives on beyond any particular implementation.

And has it changed the paths you’d suggest for someone learning web dev?

If you want one simple message, it’s JavaScript. I think you’ll turn out pretty OK if you dig way into that right now.

What’s the best tech-related thing you watched recently, and why?

I’m far from unique here, but I quite love documentaries. I feel like documentaries have a strong chance of influencing how you think. If you bring up a documentary at a dinner party, and others have seen it, it always lights up the conversation. I really enjoyed Wild Wild Country recently. I liked Fishpeople as a easy quicky inspirational documentary snackfood. I’ve seen Home Movie about a million times as that one just really resonates with (it’s about people who live in really weird houses.) If you wanna dig into a truly strange and interesting world created by one person, try Marwencol.

And finally, what was the funniest or interesting off-topic link you’ve sent to a friend recently?

Did y’all see this one-minute animated ad about the changing job market for University of Phoenix? Incredibly well done, like a dang Pixar short. It’s powerful, but of course it stirs up mixed feelings. For one, University of Phoenix doesn’t have a stellar reputation, so I’m slightly dubious that if you wanna up and change your life that that is the best way to do it.

More interestingly though, while factory jobs are being lost at a faster clip, our own industry is also worried about automation. It would be bitter irony indeed to leave a factory job, get an education, change careers, only to land in a new job that is also shortly lost to automation.

The post Versioning Interview appeared first on CSS-Tricks.

Digging Into React Context

Css Tricks - Mon, 06/11/2018 - 3:24am

You may have wondered lately what all the buzz is about Context and what it might mean for you and your React sites. Before Context, when the management of state gets complicated beyond the functionality of setState, you likely had to make use of a third party library. Thanks to recent updates by the awesome React team, we now have Context which might help with some state management issues.

What Does Context Solve?

How do you move the state from a parent component to a child component that is nested in the component tree? You know that you can use Redux to manage state, but you shouldn’t have to jump to Redux in every situation.

There's a way to do this without Redux or any other third party state management tool. You can use props!

Say the feature you want to implement has a tree structure similar to what I have below:

The state lives in the App component and is needed in UserProfile and UserDetails components. You need to pass it via props down the tree. If the components that need this state are 10 steps deep, this can become tedious, tiring, and error prone. Each component is supposed to be like a black box — other components should not be aware of states that they do not need. Here is an example of an application that matches the scenario above.

class App extends React.Component { state = { user: { username: 'jioke', firstName: 'Kingsley', lastName: 'Silas' } } render() { return( <div> <User user={this.state.user} /> </div> ) } } const User = (props) => ( <div> <UserProfile {...props.user} /> </div> ) const UserProfile = (props) => ( <div> <h2>Profile Page of {props.username}</h2> <UserDetails {...props} /> </div> ) const UserDetails = (props) => ( <div> <p>Username: {props.username}</p> <p>First Name: {props.firstName}</p> <p>Last Name: {props.lastName}</p> </div> ) ReactDOM.render(<App />, document.getElementById("root"));

We are passing the state from one component to another using props. The User component has no need of the state, but it has to receive it via props in order for it to get down the tree. This is exactly what we want to avoid.

See the Pen React Context API Pen 1 by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.

Context to the Rescue!

React’s Context API allows you to store the state in what looks like an application global state and access it only in the components that need them, without having to drill it down via props.

We start by initializing a new Context using React's createContext()

const UserContext = React.createContext({}) const UserProvider = UserContext.Provider const UserConsumer = UserContext.Consumer

This new Context is assigned to a const variable, in this case, the variable is UserContext. You can see that there is no need to install a library now that createContext() is available in React (16.3.0 and above).

The Provider component makes the context available to components that need it, which are called Subscribers. In other words, the Provider component allows Consumers to subscribe to changes in context. Remember that the context is similar to a global application state. Thus, components that are not Consumers will not be subscribed to the context.

If you are coding locally, your context file will look like this:

import { createContext } from 'react' const UserContext = createContext({}) export const UserProvider = UserContext.Provider export const UserConsumer = UserContext.Consumer The Provider

We'll make use of the Provider in our parent component, where we have our state.

class App extends React.Component { state = { user: { username: 'jioke', firstName: 'Kingsley', lastName: 'Silas' } } render() { return( <div> <UserProvider value={this.state.user}> <User /> </UserProvider> </div> ) } }

The Provider accepts a value prop to be passed to it Consumer components descendants. In this case, we will be passing the user state to the Consumer components. You can see that we are not passing the state to User component as props. That means we can edit the User component and exclude the props since it does not need them:

const User = () => ( <div> <UserProfile /> </div> ) The Consumer

Multiple components can subscribe to one Provider component. Our UserProfile component needs to make use of the context, so it will subscribe to it.

const UserProfile = (props) => ( <UserConsumer> {context => { return( <div> <h2>Profile Page of {context.username}</h2> <UserDetails /> </div> ) }} </UserConsumer> )

The data we injected into the Provider via the value prop is then made available in the context parameter of the function. We can now use this access the username of the user in our component.

The UserDetails component will look similar to the UserProfile component since it is subscriber to the same Provider:

const UserDetails = () => ( <div> <UserConsumer> {context => { return ( <div> <p>Userame: {context.username}</p> <p>First Name: {context.firstName}</p> <p>Last Name: {context.lastName}</p> </div> ) }} </UserConsumer> </div> )

See the Pen React Context API Pen 2 by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.

Updating State

What if we want to allow users to change their first and last name? That's also possible. Consumer components can re-render whenever there are changes to the value passed by the Provider component. Let's see an example.

We'll have two input fields for the first and last name in the consumer component. From the Provider component, we will have two methods that update the state of the application using the values entered in the input fields. Enough talk, let's code!

Our App component will look like this:

class App extends React.Component { state = { user: { username: 'jioke', firstName: 'Kingsley', lastName: 'Silas' } } render() { return( <div> <UserProvider value={ { state: this.state.user, actions: { handleFirstNameChange: event => { const value = event.target.value this.setState(prevState => ({ user: { ...prevState.user, firstName: value } })) }, handleLastNameChange: event => { const value = event.target.value this.setState(prevState => ({ user: { ...prevState.user, lastName: value } })) } } } }> <User /> </UserProvider> </div> ) } }

We are passing an object which contains state and actions to the value props which the Provider receives. The actions are methods that will be triggered when an onChange event happens. The value of the event is then used to update the state. Since we want to update either the first name or last name, there’s a need to preserve the value of the other. For this, we make use of ES6 Spread Operator, which allows us to update the value of the specified key.

With the new changes, we need to update UserProfile component.

const UserProfile = (props) => ( <UserConsumer> {({state}) => { return( <div> <h2>Profile Page of {state.username}</h2> <UserDetails /> </div> ) }} </UserConsumer> )

We use ES6 destructuring to extract state from the value received from the Provider.

For the UserDetails component, we both the state and actions. We also need to add two input fields that will listen for an onChange() event and call the corresponding methods.

const UserDetails = () => { return ( <div> <UserConsumer> {({ state, actions }) => { return ( <div> <div> <p>Userame: {state.username}</p> <p>First Name: {state.firstName}</p> <p>Last Name: {state.lastName}</p> </div> <div> <div> <input type="text" value={state.firstName} onChange={actions.handleFirstNameChange} /> </div> <div> <input type="text" value={state.lastName} onChange={actions.handleLastNameChange} /> </div> </div> </div> ) }} </UserConsumer> </div> ) } Using Default Values

It is possible to pass default values while initializing Context. To do this, instead of passing an empty object to createContext(), we will pass some data.

const UserContext = React.createContext({ username: 'johndoe', firstName: 'John', lastName: 'Doe' })

To make use of this data in our application tree, we have to remove the provider from the tree. So our App component will look like this.

class App extends React.Component { state = { user: { username: 'jioke', firstName: 'Kingsley', lastName: 'Silas' } } render() { return( <div> <User /> </div> ) } }

See the Pen React Context API Pen 4 by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.

The data that will be used in the Consumer components will be done defined when we initialized a new Context.

In Conclusion

When things get complicated, and you are tempted to run yarn install [<insert third-party library for state management], pause for a second — you’ve got React Context at the ready. Don't you believe me? Maybe you'll believe Kent C. Dodds.

The post Digging Into React Context appeared first on CSS-Tricks.

Syndicate content
©2003 - Present Akamai Design & Development.