Css Tricks

Syndicate content
Tips, Tricks, and Techniques on using Cascading Style Sheets.
Updated: 21 hours 42 min ago

2017/2018 JavaScript

Fri, 01/19/2018 - 1:46pm

There has been a lot of research on the landscape this year! Here are a few snippets from a bunch of articles. There is a ton of information in each, so I'm just picking out a few juicy quotes from each here.

Perhaps the most interesting bit is how different the data looked at is. Each of these is different: a big developer survey, npm data, GitHub data, and StackOverflow data. Yet, they mostly tell the same stories.

The Brutal Lifecycle of JavaScript Frameworks

Ian Allen of StackOverflow writes:

JavaScript UI frameworks and libraries work in cycles. Every six months or so, a new one pops up, claiming that it has revolutionized UI development. Thousands of developers adopt it into their new projects, blog posts are written, Stack Overflow questions are asked and answered, and then a newer (and even more revolutionary) framework pops up to usurp the throne.

Using the Stack Overflow Trends tool and some of our internal traffic data, we decided to take a look at some of the more prominent UI frameworks: Angular, React, Vue.js, Backbone, Knockout, and Ember.

Read More

The Top JavaScript Trends to Watch in 2018

Ryan Chartrand of X-Team for Hackernoon writes:

This time last year, not many had faith that Vue would ever become a big competitor to React when it comes to major companies adopting it, but it was impossible to ignore Vue this year, even sending Angular a bit into the shadows in terms of developer hype.

Read More

The State of JavaScript 2017

Sacha Greif uses a survey rather than usage data:

We asked over a hundred questions to more than 28,000 developers all over the world, covering topics going from front-end libraries all the way to back-end frameworks.

I particularly enjoyed the opinions. Lots of people who love working with JavaScript and find it to be moving in the right direction and find it overly complex.

Read More

The State of JavaScript Frameworks, 2017

This one is from Laurie Voss of npm, which is probably the best source of data for usage but faces interesting challenges with that data:

You can use npm’s download statistics to give you insight into the amount of people actively invested in using and maintaining a package. However, probably more important than absolute popularity is growth.

Packages, once incorporated into software, have very long lives. People very seldom rip packages out of software once they’re installed. Because of this very low “churn,” packages hardly ever decline in usage. Furthermore, nearly all packages in the npm Registry grow in usage as the number of total npm users continues to skyrocket. They vary only in how fast they’re growing.

This makes measuring growth harder, since measuring absolute growth in downloads all the time makes almost everything look popular.

All in all it tells a familiar story: React is incredibly popular and Vue is the one to watch.

Read More

Top JavaScript Libraries & Tech to Learn in 2018

Eric Elliott writes:

Vue.js did do very well in 2017. It got a lot of headlines and a lot of people got interested. As I predicted, it did not come close to unseating React, and I’m confident to predict it won’t unseat React in 2018, either. That said, it could overtake Angular in 2018.

Read More

2017 JavaScript Rising Stars

Michael Rambeau's writes:

Once again, Vue.js is the trendiest project of the year, with more than 40,000 stars added on GitHub during the year.

It's far more than in 2016 (26,000 stars), and the gap with the next contender (React) is even bigger.

Read More

2017/2018 JavaScript is a post from CSS-Tricks

Secure Contexts Everywhere

Fri, 01/19/2018 - 8:55am

Anne van Kesteren for Mozilla says:

Effective immediately, all new features that are web-exposed are to be restricted to secure contexts. Web-exposed means that the feature is observable from a web page or server, whether through JavaScript, CSS, HTTP, media formats, etc. A feature can be anything from an extension of an existing IDL-defined object, a new CSS property, a new HTTP response header, to bigger features such as WebVR. In contrast, a new CSS color keyword would likely not be restricted to secure contexts.

In other words, if your site isn't HTTPS, you won't get new web tech features. Holy jeepers. The reasoning is the web should be using HTTPS, so this is our way of beating you with a stick if you try to use fancy features without going HTTPS first.

It'll be fascinating to watch the first major feature drop and if they stick to their word here. The web dev forums of the internet will overflow with WHY DOESN'T grid-gap WORK WITH MY FLEXBOX? (or some likely coming-soon feature) questions and the answer will be: talk to your server team. What if they drop container queries behind this? That would be a hilarious devastating tornado of developer fury.

Direct Link to ArticlePermalink

Secure Contexts Everywhere is a post from CSS-Tricks

Creating a Vue.js Serverless Checkout Form: Configure the Checkout Component

Fri, 01/19/2018 - 5:54am

This is the fourth post in a four-part series. In Part one, we set up a serverless Stripe function on Azure. Part two covered how we hosted the function on Github. The third part covered Stripe Elements in Vue. This last post shows how to configure the checkout component and make the shopping cart fully functional.

Article Series:
  1. Setup and Testing
  2. Stripe Function and Hosting
  3. Application and Checkout Component
  4. Configure the Checkout Component (This Post)

As a reminder, here's where we are in our application at this point:

Configuring the Checkout Component

We have to do a few things to adjust the component in order for it to meet our needs:

  • Make sure the form is only displaying if we haven't submitted it—we'll deal with the logic for this in our pay method in a moment
  • Allow the form to take a customer's email address in case something is wrong with the order.
  • Disable the submit button until the required email address is provided
  • Finally and most importantly, change to our testing key

Here's our updated checkout component with the changes to the original code highlighted:

<div v-if="!submitted" class="payment"> <h3>Please enter your payment details:</h3> <label for="email">Email</label> <input id="email" type="email" v-model="stripeEmail" placeholder="name@example.com"/> <label for="card">Credit Card</label> <p>Test using this credit card: <span class="cc-number">4242 4242 4242 4242</span>, and enter any 5 digits for the zip code</p> <card class='stripe-card' id="card" :class='{ complete }' stripe='pk_test_5ThYi0UvX3xwoNdgxxxTxxrG' :options='stripeOptions' @change='complete = $event.complete' /> <button class='pay-with-stripe' @click='pay' :disabled='!complete || !stripeEmail'>Pay with credit card</button> </div>

There are a number of things we need to store and use for this component, so let's add them to data or bring them in as props. The props that we need from our parent component will be total and success. We'll need the total amount of the purchase so we can send it to Stripe, and the success will be something we need to coordinate between this component and the parent, because both components need to know if the payment was successful. I write out the datatypes as well as a default for my props.

props: { total: { type: [Number, String], default: '50.00' }, success: { type: Boolean, default: false } },

Next, the data we need to store will be the stripeEmail we collected from the form, stripeOptions that I left in to show you can configure some options for your form, as well as status and response that we'll get from communicating with the server and Stripe. We also want to hold whether or not the form was submitted, and whether the form was completed for enabling and disabling the submit button, which can both be booleans.

data() { return { submitted: false, complete: false, status: '', response: '', stripeOptions: { // you can configure that cc element. I liked the default, but you can // see https://stripe.com/docs/stripe.js#element-options for details }, stripeEmail: '' }; },

Now for the magic! We have everything we need—we just need to alter our pay() method, which will do all the heavy lifting for us. I'm going to use Axios for this, which will receive and transform the data:

npm i axios --save

...or using Yarn:

yarn add axios

If you're not familiar with Axios and what it does, check out this article for some background information.

pay() { createToken().then(data => { this.submitted = true; // we'll change the flag to let ourselves know it was submitted console.log(data.token); // this is a token we would use for the stripeToken below axios .post( 'https://sdras-stripe.azurewebsites.net/api/charge?code=zWwbn6LLqMxuyvwbWpTFXdRxFd7a27KCRCEseL7zEqbM9ijAgj1c1w==', { stripeEmail: this.stripeEmail, // send the email stripeToken: data.token.id, // testing token stripeAmt: this.total // send the amount }, { headers: { 'Content-Type': 'application/json' } } ) .then(response => { this.status = 'success'; this.$emit('successSubmit'); this.$store.commit('clearCartCount'); // console logs for you :) this.response = JSON.stringify(response, null, 2); console.log(this.response); }) .catch(error => { this.status = 'failure'; // console logs for you :) this.response = 'Error: ' + JSON.stringify(error, null, 2); console.log(this.response); }); }); },

The code above does a number of things:

  • It allows us to track whether we've submitted the form or not, with this.submitted
  • It uses Axios to post to our function. We got this URL from going to where the function lives in the portal, and clicking "Get Function URL" on the right side of the screen.
  • It sends the email, token, and total to the serverless function
  • If it's successful, it changes the status to success, commits to our Vuex store, uses a mutation to clear our cart, and emits to the parent cart component that the payment was successful. It also logs the response to the console, though this is for educational purposes and should be deleted in production.
  • If it errors, it changes the status to failure, and logs the error response for help with debugging

If the payment fails, which we'll know from our status, we need to let the user know something went wrong, clear our cart, and allow them to try again. In our template:

<div v-if="status === 'failure'"> <h3>Oh No!</h3> <p>Something went wrong!</p> <button @click="clearCheckout">Please try again</button> </div>

The button executes the following clearCheckout method that clears a number of the fields and allow the customer to try again:

clearCheckout() { this.submitted = false; this.status = ''; this.complete = false; this.response = ''; }

If the payment succeeds, we will show a loading component, that will play an SVG animation until we hear back from the server. Sometimes this can take a couple of seconds, so it's important that our animation make sense if it is seen for a short or long amount of time, and can loop as necessary.

<div v-else class="loadcontain"> <h4>Please hold, we're filling up your cart with goodies</h4> <app-loader /> </div>

Here's what that looks like:

See the Pen shop loader by Sarah Drasner (@sdras) on CodePen.

Now if we revisit the first cart component we looked at in pages/cart.vue, we can fill that page based on the logic we set up before because it's been completed:

<div v-if="cartTotal > 0"> <h1>Cart</h1> ... <app-checkout :total="total" @successSubmit="success = true"></app-checkout> </div> <div v-else-if="cartTotal === 0 && success === false" class="empty"> <h1>Cart</h1> <h3>Your cart is empty.</h3> <nuxt-link exact to="/"><button>Fill 'er up!</button></nuxt-link> </div> <div v-else> <app-success @restartCart="success = false"/> <h2>Success!</h2> <p>Your order has been processed, it will be delivered shortly.</p> </div>

If we have items in our cart, we show the cart. If the cart is empty and the success is false, we'll let them know that their cart is empty. Otherwise, if the checkout has just been processed, we'll let them know that everything has been executed successfully!

We are now here:

In the AppSuccess.vue component, we have a small SVG animation designed to make them feel good about the purchase:

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

(You may have to hit "Rerun" to replay the animation.)

We also put a small timer in the mounted() lifecycle hook:

window.setTimeout(() => this.$emit('restartCart'), 3000);

This will show the success for three seconds while they read it then kick off the restartCart that was shown in the component above. This allows us to reset the cart in case they would like to continue shopping.


You learned how to make a serverless function, host it on Github, add required dependencies, communicate with Stripe, set up a Shopping Cart in a Vue application, establish a connection with the serverless function and Stripe, and handle the logic for all of the cart states. Whew, way to go!

It's worth mentioning that the demo app we looked at is a sample application built for specifically for this purpose of this tutorial. There are a number of steps you'd want to go through for a production site, including testing, building the app's dist folder, and using real Stripe keys. There are also so many ways to set this up, Serverless functions can be so flexible in tandem with something like Vue. Hopefully this gets you on track and saves you time as you try it out yourself.

Creating a Vue.js Serverless Checkout Form: Configure the Checkout Component is a post from CSS-Tricks

The Ultimate Guide to Headless CMS

Thu, 01/18/2018 - 11:26am

(This is a sponsored post.)

The World Has Changed—So Must the CMS

Having a responsive website is no longer enough. Your audience expects a seamless and personalized customer experience across all their devices—the age of headless technology is coming.

Headless CMS is the next generation in content management for brands that want to stay ahead of the curve by engaging customers through the growing number of channels.

Download The Ultimate Guide to Headless CMS ebook for a deep look into what headless CMS is, and why it should be at the top of your list when choosing a new CMS.

Download the ebook now!

Direct Link to ArticlePermalink

The Ultimate Guide to Headless CMS is a post from CSS-Tricks

Get Ready for `display: contents;`

Thu, 01/18/2018 - 9:24am

Last year I asked, "Will we be flattening our HTML for CSS Grids?"

The issue is that the only way for elements to participate in the same CSS grid together (or flexbox for that matter) is for them to be siblings. So, in some cases we might be incentivized to forego HTML semantics for the benefit of layout (not great).

One answer to this is display: contents;—a magical new display value that essentially makes the container disappear, making the child elements children of the element the next level up in the DOM.

Fast forward to today, Chrome is shipping it, WebKit is shipping it, and Firefox has shipped it. Vote for it in Edge here.

Wanna understand it better? Rachel Andrew wrote "Vanishing boxes with display contents" and clarifies how it all works:

This value becomes useful if you want to add some element because it makes sense in terms of document semantics, but doesn’t in terms of display. Perhaps you have some content that makes sense marked up as an article, that article is then a flex item in your layout BUT the elements you really would like to be flex items are nested inside that article. Rather than flattening your markup and remove the article element to enable these inner elements to be part of the flex layout, you could remove the boxes generated by article using display: contents. You then get the best of both worlds, semantic markup plus the visual display your design requires. That sounds good to me.

Manuel Rego takes a stab at explaining it as well:

display: contents makes that the div doesn’t generate any box, so its background, border and padding are not rendered. However the inherited properties like color and font have effect on the child (span element) as expected.

There is also a very related subject to all this: subgrids. Probably literally display: subgrid;. It's probably less important in terms of maintaining semantics than display: contents; but also different.

Eric Meyer called subgrids essential:

Grid layout is the first serious candidate to fill that hole in the past two decades, and I don’t want to see them hamstrung from the outset. Subgrids are essential to the adoption of grids. I hope they’ll be implemented as soon as possible

And to understand the difference, Rachel Andrew also wrote "Why display: contents is not CSS Grid Layout subgrid":

You won’t get far through a conversation about subgrid in CSS Grid Layout without someone suggesting that display: contents solves most of the problems anyway, so do we really need subgrid? This really isn’t the case, display: contents does indeed solve a class of problems, but these are different problems to those that subgrid would help us with.

Get Ready for `display: contents;` is a post from CSS-Tricks

Creating a Vue.js Serverless Checkout Form: Application and Checkout Component

Thu, 01/18/2018 - 5:07am

This is the third post in a four-part series. In part one, we set up a serverless Stripe function on Azure. Part two covered how we hosted the function on Github. This post will focus on wiring everything up as a Vue.js application.

Article Series:
  1. Setup and Testing
  2. Stripe Function and Hosting
  3. Application and Checkout Component (This Post)
  4. Configure the Checkout Component

Stripe has a number of ways to build out a checkout form, the most basic being a single button on the page that you trigger to pull up their custom modal. There’s a repo and component for this, but as easy as that is to implement (it's probably the most simple way to do it), I wanted a little more customization and wanted the checkout flow to be part of the page and application. This approach wouldn’t work for my needs.

Stripe Elements

Stripe also offers a thing called Elements. Elements allow you to integrate Stripe's payment system into your own checkout form and style it like your own site for a cohesive experience. It won't feel like you're using a third party plugin. They do have some pre-styled examples if you prefer something you can use right out of the box.

Luckily for us, there's a really nice repo with a Vue version of Stripe Elements called vue-stripe-elements. The repo's documentation is really nice, so you could check that out. Here's how I put it to use:

npm i vue-stripe-elements-plus --save

...or using Yarn:

yarn add vue-stripe-elements-plus

Now let's talk about our cart and integrate it.

The Cart

Here's what everything looks like as a birds eye view of the application. We've already addressed the function and stripe pieces, now let's dig into the application itself.

We're not going to go through setting up the entire application in these posts, rather just the Cart and Checkout. I'd suggest checking out the following links before continuing if you need to catch up on the basics of Vue, Vuex, and Nuxt:

In our general store set up with Vuex, we hold a manifest of all of our product data used to populate the pages with items. We'll also use that information to populate a (currently empty) cart object where items can be added for purchase. We'll use that data on a page called `Cart.vue` in the pages directory. If you're unfamiliar with Nuxt.js, it allows us to use .vue components as pages by creating them in this pages directory. We can still populate these pages with components from the components directory to create a more modular application. Here are the parts we're discussing now:

We'll need two pieces of information from that store in Vuex: the contents of the cart and the cartTotal.

We'll use computed properties in pages/Cart.vue to fetch that information so that we can cache and use them in the cart.

computed: { cart() { return this.$store.state.cart; }, cartTotal() { return this.$store.state.cartTotal; }, ... }

...and we'll create a new computed property that will store the monetary total of the items in the cart as well:

computed: { ... total() { return Object.values(this.cart) .reduce((acc, el) => acc + (el.count * el.price), 0) .toFixed(2); } }

The first thing that we'll do is see if the cart has items in it. If it does, then we need to check that the payment hasn't already been processed. We need to do this because there's no need to display a checkout form if there are no items in the cart or if payment has already been processed for the items that were added.

<div v-if="cartTotal > 0"> <!--we'll add our checkout here--> </div> <!--If the cart is empty, give them the ability to get back to the main page to add items--> <div v-else-if="cartTotal === 0 && success === false" class="empty"> <!--we'll add our empty state here--> </div> <!--If there's a success, let's let people know it's being processed, we'll add a success component later on--> <div v-else> <!--we'll add success here--> </div>

We'll also create a success property in our data that we'll initially set to false and use later to record whether or not a payment was successfully submitted.

data() { return { success: false }; },

We want to show cart items if they exist, their individual totals (as we can have multiple counts of the same item) and the final total.

<div v-if="cartTotal > 0"> <h1>Cart</h1> <div class="cartitems" v-for="item in cart" key="item"> <div class="carttext"> <h4>{{ item.name }}</h4> <p>{{ item.price | usdollar }} x {{ item.count }}</p> <p>Total for this item: <strong>{{ item.price * item.count }}</strong></p> </div> <img class="cartimg" :src="`/${item.img}`" :alt="`Image of ${item.name}`"> </div> <div class="total"> <h3>Total: {{ total | usdollar }}</h3> </div> <!--we're going to add our checkout here--> </div>

We're using a filter to format the prices in US dollars. I format them this way instead of hardcoding them in case I need to support other currencies in the future.

filters: { usdollar: function(value) { return `$${value}`; } } Setting up the Checkout Component

Now we're going to create our checkout component, which will hold all of the Stripe checkout logic and connect to the serverless function we set up in Part Two. We'll register the component in the Cart.vue file:

import AppCheckout from './../components/AppCheckout.vue'; export default { components: { AppCheckout }, ... }

Here's where we're at now:

And, in the checkout component itself, we'll bring over the base for the file that we saw in the vue-stripe-elements repo documentation:

<template> <div id='app'> <h1>Please give us your payment details:</h1> <card class='stripe-card' :class='{ complete }' stripe='pk_test_XXXXXXXXXXXXXXXXXXXXXXXX' :options='stripeOptions' @change='complete = $event.complete' /> <button class='pay-with-stripe' @click='pay' :disabled='!complete'>Pay with credit card</button> </div> </template> <script> import { stripeKey, stripeOptions } from './stripeConfig.json' import { Card, createToken } from 'vue-stripe-elements-plus' export default { data () { return { complete: false, stripeOptions: { // see https://stripe.com/docs/stripe.js#element-options for details } } }, components: { Card }, methods: { pay () { // createToken returns a Promise which resolves in a result object with // either a token or an error key. // See https://stripe.com/docs/api#tokens for the token object. // See https://stripe.com/docs/api#errors for the error object. // More general https://stripe.com/docs/stripe.js#stripe-create-token. createToken().then(data => console.log(data.token)) } } } </script> Next Up...

So far, this is what the component looks like out of the box. We're going to have to update this component a bit to fit our needs, but not too much. Stay tuned tomorrow for the final installment when we connect our component to our serverless function and finish up the checkout!

Article Series:
  1. Setup and Testing
  2. Stripe Function and Hosting
  3. Application and Checkout Component (This Post)
  4. Configure the Checkout Component

Creating a Vue.js Serverless Checkout Form: Application and Checkout Component is a post from CSS-Tricks

Creating a Vue.js Serverless Checkout Form: Stripe Function and Hosting

Wed, 01/17/2018 - 4:44am

We're now in the second post of a four-part series where we're creating a checkout form application in Vue.js that can accept payments via the Stripe API. In part one, we looked at the concept of serverless functions, set one up in Azure, and connected it to a Stripe account. In this post, we'll focus on setting up Stripe as a serverless function and hosting it all on Github.

Article Series:
  1. Setup and Testing
  2. Stripe Function and Hosting (This Post)
  3. Application and Checkout Component
  4. Configure the Checkout Component

First, we’re going write our function and test it out in the portal, but eventually we’re going to move it over to Github and have Azure pull in the code. I’ll explain why we do this in a moment.

For now, in order to get it working and testable, we’re going to write it in the portal and fill in the request body to perform the test. But we need to know what Stripe will expect from us first.

Dun dun dun...

Working With Stripe as a Serverless Function

If you check out Stripe's documentation, you can see that we’ll need to grab the Stripe token in the dashboard. This will eventually mirror the POST parameters submitted by our form. Stripe makes it easy, so it's fairly straightforward to use their library for the server-side function with Express:

app.get('/', (req, res) => res.render('index.pug', { keyPublishable })); app.post('/charge', (req, res) => { let amount = 500; stripe.customers .create({ email: req.body.stripeEmail, source: req.body.stripeToken }) .then(customer => stripe.charges.create({ amount, description: 'Sample Charge', currency: 'usd', customer: customer.id }) ) .then(charge => res.render('charge.pug')); }); app.listen(4567);

We won’t need to set up all of Node and Express for this, though, as what we really need is the amount, the currency, the description, and the token, which we can integrate with the testing code we were provided earlier in the portal's view of our function. So, let’s head over to the Azure portal where our function lives and update that default testing code to accept the parameters we need for Stripe, and also populate the request.body in the test panel.

We’ll add our Stripe testing key and kick everything off. To be totally sure, we’re going to log what we’ve gotten started:

var stripe = require('stripe')('sk_test_whateveryourtestingkeyisgoeshere'); // ^ this is a stripe testing key module.exports = function(context, req) { context.log('starting to get down');

If we have a request body, an email, and a token, then let's get started. We’ll create a customer from the email and then use that customer to create the Stripe charges, passing in the amount of the charge as we do so.

if ( req.body && req.body.stripeEmail && req.body.stripeToken && req.body.stripeAmt ){ stripe.customers .create({ email: req.body.stripeEmail, source: req.body.stripeToken }) .then(customer => { context.log('starting the stripe charges'); stripe.charges.create({ amount: req.body.stripeAmt, description: 'Sample Charge', currency: 'usd', customer: customer.id }); }) ...

We also want to test if this all completed successfully, or if it errored out. If it did error, we need to log what that error is. We’ll also see if the whole thing errored entirely, making sure we’re logging everything appropriately along the way.

You'll note that I log a lot. I think it's not enough to know that something has errored. I want to know when the error happened and why so that I can track it down. This makes it much easier to debug if something were to go wrong.

... .then(charge => { context.log('finished the stripe charges'); context.res = { // status: 200 body: 'This has been completed' }; context.done(); }) .catch(err => { context.log(err); context.done(); }); } else { context.log(req.body); context.res = { status: 400, body: "We're missing something" }; context.done(); } };

In the testing area on the right side of the portal, we’ll fill the request.body with the stripeEmail, stripeToken (a testing token in this case), and some random amount for the charge. When we run this, we can see that it works! We get a 200 OK Status, and we’ve logged This has been completed in the output.

Testing the request body parameters with the actual function in Azure. Github-Hosted Serverless Function

Let's put everything in Github now that it's working. One big reason we want to do this is because our function will have a dependency on Stripe’s library. If you head over to the sample-stripe-handler repo I’ve created for this tutorial, you’ll see a package.json file. The most important lines in that file are these:

"dependencies": { "stripe": "^5.3.0" }

This tells the function to pull in the correct version of the Stripe API that we need to use in order for our app to properly function. As a note, you could also use this method to write other kinds of functions using other libraries. This means the possibilities for what to create are endless!

We'll pull everything from our function into this repo. This includes the function itself, the package.json file, as well as the contents of the function.json file that you'll see in the "View Files" tab on the right in the Azure portal.

Once we have that all in ready to go in a Github repo, we'll head back over to the Azure portal, because now we have to let Azure know that we'd like to use this repo to host our function instead of our test. We can still test our function inside the portal—we just won't be able to edit it via the GUI anymore.

Click on the “Platform Features” tab and select the “Deployment Options” item.

From here, click "Settings" then "Choose source" and a number of options will be provided. I’m going to choose Github because that’s where I want to host mine, but you can see that there are a lot of other ways we could have done this.

Deployment settings source options, including Github.

Once Github has been selected, you will be able to configure which repo you would like to use as your deployment source. I chose the sample-stripe-handler repo that we created earlier.

Configuring Github as the deployment source.

After we’ve done this and it’s loaded, you’ll be taken to a "Deployments" screen that shows the last commit that you made to the repo. That means everything’s working correctly!

Let’s test this a little further. My function didn’t work properly the first time because I was using ES6. I could have added in Babel, but I just converted it back to ES5 and pushed to the master branch. You can see the function.json becomes inactive as the last deployment, and my latest commit message—which is mostly me grumbling—is now the latest deploy! Awesome.

We can't be too careful so, to check that these tests did indeed work, I’m going to head over to the Stripe dashboard. Sure enough, there are testing charges showing up in our dashboard &#x1f600;

One last thing!

We would be remiss to exclude our good friend CORS, which we need to properly enable for everything to communicate as it should. Let's go to our function in the dashboard, and select CORS:

In the prompt that appears, we'll whitelist our localhost dev server, as well as our final URL for the site. Voila! We're all set.

Next Up...

We got a lot done in this post! Next, we'll want to learn how to move away from testing only within the function and get this sucker communicating freely with a checkout experience that we’ll build within a Vue.js application. Stay tuned!

Article Series:
  1. Setup and Testing
  2. Stripe Function and Hosting (This Post)
  3. Application and Checkout Component
  4. Configure the Checkout Component

Creating a Vue.js Serverless Checkout Form: Stripe Function and Hosting is a post from CSS-Tricks

“Stop Using CSS Selectors for Non-CSS”

Tue, 01/16/2018 - 12:14pm

I saw Nicole Dominguez tweet this the other day:

say it louder for the people in the backhttps://t.co/prDKo5QaZi

— nicole (@sodevious) January 11, 2018

I wasn't at this conference, so I have very little context. Normally, I'd consider it a sin to weigh in on a subject brought up by looking at two out-of-context slides, but I'm only weighing in out of interest and to continue the conversation.

The idea seems to be that if you need to select an element in the DOM with JavaScript, don't use the same selector as you would in CSS.

So if you have...

<article class="article"> </article>

...and you need to apply an event listener to that article for some reason, then don't use...


(or querySelector or whatever, I assume.)

Instead, apply an attribute intended just for the JavaScript to target, like...

<article class="article" data-hoverable> </article>

...and target that like...


The idea is that you can separate jobs. The class has the job of styling, and the data attribute has the job of JavaScripting. Both can change without affecting each other.

Seems reasonable to me.

Also seems like there is plenty to talk about here. Performance, I suppose, but that's probably the least-interesting thing since selectors are generally pretty damn fast these days. We could continue the conversation by talking about:

  • What naming convention?
  • Should you be naming events?
  • What if it needs to be selected for different reasons multiple times?
  • Can you or should you use IDs?
  • Is it worth avoiding DOM selection at all if you can?
  • What other nuances are part of this discussion?

I saw Michael Scharnagl had some thoughts on his own usage of ID's, classes, and data-attributes that could help frame things a bit.

“Stop Using CSS Selectors for Non-CSS” is a post from CSS-Tricks

Creating a Vue.js Serverless Checkout Form: Setup and Testing

Tue, 01/16/2018 - 5:19am

There comes a time in any young app’s life when it will have to monetize. There are a number of ways to become profitable, but accepting cash is a surefire way to make this more direct. In this four-part tutorial, we’ll go over how to set up a serverless function, make it talk to the Stripe API, and connect it to a checkout form that is setup as a Vue application. This may sound daunting, but it’s actually pretty straightforward! Let's dig in.

Article Series:
  1. Setup and Testing (This Post)
  2. Stripe Function and Hosting
  3. Application and Checkout Component
  4. Configure the Checkout Component
What is Serverless?

We’ve covered serverless concepts before but, in case you haven’t read that article, let’s talk for a minute about what we mean by "serverless” because it’s a bit of a misnomer.

The promise of serverless is to spend less time setting up and maintaining a server. You're essentially letting the service handle maintenance and scaling for you, and you boil what you need down to functions that run certain code when a request is made. For this reason, people may refer to this as FaaS. This is really useful because you pay for what you use, rather than a large container that you might not need in its entirety. You also primarily hunker down and focus just on the code you need to run instead of babysitting a server, which really appeals to a lot of people who’d like to get up and running quickly.

But FaaS isn't always the right tool for the job. It's really useful for small executions but, if you have processes that might hold up resources or a ton of computation, being able to communicate with a server as you normally do might be more efficient.

What we’re going to make is a perfect use case for going serverless. Stripe checkouts are pretty seamless to integrate on both the client and server side, but we do actually need to execute some logic on the server, so we’ll use Azure to help us with this. The portal and Github integration are pretty quick to manipulate, as long as you know where to go. So by all means, let’s make it happen!

Sign up for Stripe

First, we’ll create a Stripe account. We verify our new account via email and then we’ll head over to the API section, where we can retrieve two keys. You’ll note that we’re in test mode right now, which is good! We’ll keep it like that for testing, and unveil the testing key token to use while we set up the application.

Once you're signed in, go to the API section of your dashboard to retrieve your key.

The Stripe API screen

You may also want to add a phone number to your account for 2 factor auth as well.

Setting up Our Serverless Function in the Azure Portal

First, we’ll head over to the portal, (or if you don't already have an account, you can sign up for a free trial here) and select New > Serverless Function

Setting up a new Servless Function in Azure

When we click on the Serverless Function app, we’ll be taken to a panel that asks for details to help with the setup. As you can see in the screenshot above, it will autofill most of the fields just from the app name, but let's go over some of these options quickly:

  • Add in a unique name
  • A Resource Group (if you don’t already have one, create one)
  • I use the Windows OS because the Linux is still in preview, so Windows will be more stable
  • I use the Consumption Plan because this is the one that will have payments that scale with the use, and it will also scale automatically. The other option, App Service Plan, is good for people who prefer everything to be a bit more manual.
  • Choose a location that is close to your customer base, or a midpoint between two customer bases
  • Choose a storage, or create one as I’ve done
  • I’ll also check Pin to Dashboard because I want to be able to retrieve my function quickly later

This will bring you back to the main portal dashboard and let you know that your function is deploying. Once it’s done, it take you to a main screen that has all of your options. From here, we’ll want to create our function, and it will be an HTTP trigger.

We’ll select Functions under our function name, and you’ll see a little table with a plus that says “New Function”:

Once we click here, we have a few options on what we can create. We’ll pick HTTP Trigger:

We’ll be able to select the language (pick "JavaScript") and then "Create":

The Default Testing Function

From here, we’re given a default testing function which helps us see how this all works. If we open all of these panels and hit the Run button, we’ll see the output in logs.

Running the function in a test environment

Here’s the code we were given:

module.exports = function(context, req) { context.log('JavaScript HTTP trigger function processed a request.'); if (req.query.name || (req.body && req.body.name)) { context.res = { // status: 200, /* Defaults to 200 */ body: 'Hello ' + (req.query.name || req.body.name) }; } else { context.res = { status: 400, body: 'Please pass a name on the query string or in the request body' }; } context.done(); };

You’ll see here that we’re passing in the context. That allows us to log, which will be shown in the lowest panel below. In the Test panel on the right, we can pass in a request body that can be used to test our application. When it runs, we see the output with a 200 status and know that everything is working. We also have a context.log for the case that it gives us a 400 error. If you'd like to play around with a serverless function and see it in action for yourself, you can create one with a free trial account.

Next Up...

Now that we have the base of our serverless function, let's set up what we'll need to communicate with Stripe! More to come in the next post in this series.

Article Series:
  1. Setup and Testing (This Post)
  2. Stripe Function and Hosting
  3. Application and Checkout Component
  4. Configure the Checkout Component

Creating a Vue.js Serverless Checkout Form: Setup and Testing is a post from CSS-Tricks

Meet the New Dialog Element

Mon, 01/15/2018 - 1:36pm

Keith Grant discusses how HTML 5.2 has introduced a peculiar new element: <dialog>. This is an absolutely positioned and horizontally centered modal that appears on top of other content on a page. Keith looks at how to style this new element, the basic opening/closing functionality in JavaScript and, of course, the polyfills that we’ll need to get cross-browser support right.

Also, I had never heard of the ::backdrop pseudo element before. Thankfully the MDN documentation for this pseudo element digs into it a little bit more.

Direct Link to ArticlePermalink

Meet the New Dialog Element is a post from CSS-Tricks

Simplifying the Apple Watch Breathe App Animation With CSS Variables

Mon, 01/15/2018 - 5:00am

When I saw the original article on how to recreate this animation, my first thought was that it could all be simplified with the use of preprocessors and especialy CSS variables. So let's dive into it and see how!

The result we want to reproduce. The structure

We keep the exact same structure.

In order to avoid writing the same thing multiple times, I chose to use a preprocessor.

My choice of preprocessor always depends on what I want to do, as, in a lot of cases, something like Pug offers more flexibility, but other times, Haml or Slim allow me to write the least amount of code, without even having to introduce a loop variable I wouldn't be needing later anyway.

Until recently, I would have probably used Haml in this case. However, I'm currently partial to another technique that lets me avoid setting the number of items both in the HTML and CSS preprocessor code, which means I avoid having to modify it in both if I need to use a different value at some point.

To better understand what I mean, consider the following Haml and Sass:

- 6.times do .item $n: 6; // number of items /* set styles depending on $n */

In the example above, if I change the number of items in the Haml code, then I need to also change it in the Sass code, otherwise things break. In a more or less obvious manner, the result is not the intended one anymore.

So we can go around that by setting the number of circles as the value of a CSS variable we later use in the Sass code. And, in this situation, I feel better using Pug:

- var nc = 6; // number of circles .watch-face(style=`--nc: ${nc}`) - for(var i = 0; i < nc; i++) .circle(style=`--i: ${i}`)

We've also set the index for every .circle element in a similar manner.

The basic styles

We keep the exact same styles on the body, no change there.

Just like for the structure, we use a preprocessor in order to avoid writing almost the same thing multiple times. My choice is Sass because that's what I'm most comfortable with, but for something simple like this demo, there's nothing in particular about Sass that makes it the best choice - LESS or Stylus do the job just as well. It's just faster for me to write Sass code, that's all.

But what do we use a preprocessor for?

Well, first of all, we use a variable $d for the diameter of the circles, so that if we want to make them bigger or smaller and also control how far out they go during the animation, we only have to change the value of this variable.

In case anyone is wondering why not use CSS variables here, it's because I prefer to only take this path when I need my variables to be dynamic. This is not the case with the diameter, so why write more and then maybe even have to come up with workarounds for CSS variable bugs we might run into?

$d: 8em; .circle { width: $d; height: $d; }

Note that we are not setting any dimensions on the wrapper (.watch-face). We don't need to.

In general, if the purpose of an element is just to be a container for absolutely positioned elements, a container on which we apply group transforms (animated or not) and this container has no visible text content, no backgrounds, no borders, no box shadows... then there's no need to set explicit dimensions on it.

A side effect of this is that, in order to keep our circles in the middle, we need to give them a negative margin of minus the radius (which is half the diameter).

$d: 8em; $r: .5*$d; .circle { margin: -$r; width: $d; height: $d; }

We also give them the same border-radius, mix-blend-mode and background as in the original article and we get the following result:

The expected result so far (live demo).

Well, we get the above in WebKit browsers and Firefox, as Edge doesn't yet support mix-blend-mode (though you can vote for implementation and please do that if you want to see it supported because your votes do count), so it shows us something a bit ugly:

The Edge result doesn't look that good.

To get around this, we use @supports:

.circle { /* same styles as before */ @supports not (mix-blend-mode: screen) { opacity: .75 } }

Not perfect, but much better:

Using @supports and opacity to fix the lack of mix-blend-mode support in Edge (live demo).

Now let's look a bit at the result we want to get:

The desired result.

We have six circles in total, three of them in the left half and three others in the right half. They all have a background that's some kind of green, those in the left half a bit more towards yellow and those in the right half a bit more towards blue.

If we number our circles starting from the topmost one in the right half and then going clockwise, we have that the first three circles are in the right half and have a bluish green background and the last three are in the left half and have a yellowish green background.

At this point, we've set the background for all the circles to be the yellowish blue one. This means we need to override it for the first half of the six circles. Since we cannot use CSS variables in selectors, we do this from the Pug code:

- var nc = 6; // number of circles style .circle:nth-child(-n + #{.5*nc}) { background: #529ca0 } .watch-face(style=`--nc: ${nc}`) - for(var i = 0; i < nc; i++) .circle(style=`--i: ${i}`)

In case you need a refresher on this, :nth-child(-n + a) selects the items at the valid indices we get for n ? 0 integer values. In our case, a = .5*nc = .5*6 = 3, so our selector is :nth-child(-n + 3).

If we replace n with 0, we get 3, which is a valid index, so our selector matches the third circle.

If we replace n with 1, we get 2, also a valid index, so our selector matches the second circle.

If we replace n with 2, we get 1, again valid, so our selector matches the first circle.

If we replace n with 3, we get 0, which isn't a valid index, as indices are not 0-based here. At this point, we stop as it becomes clear we won't be getting any other positive values if we continue.

The following Pen illustrates how this works - the general rule is that :nth-child(-n + a) selects the first a items:

See the Pen by thebabydino (@thebabydino) on CodePen.

Returning to our circular distribution, the result so far can be seen below:

See the Pen by thebabydino (@thebabydino) on CodePen.


First off, we make the wrapper relatively positioned and its .circle children absolutely positioned. Now they all overlap in the middle.

See the Pen by thebabydino (@thebabydino) on CodePen.

In order to understand what we need to do next, let's take a look at the following illustration:

The rightmost circle going from its initial to its final position (live).

The central points of the circles in the initial position are on the same horizontal line and a radius away from the rightmost circle. This means we can get to this final position by a translation of a radius $r along the x axis.

But what about the other circles? Their central points in the final position are also a radius away from their initial position, only along other lines.

All circles: initial position (dead in the middle) is a radius away from the final one for each and every one of them (live).

This means that, if we first rotate their system of coordinates until their x axis coincides with the line between the initial and final position of the central points and then translate them by a radius, we can get them all in the correct final position in a very similar manner.

See the Pen by thebabydino (@thebabydino) on CodePen.

Alright, but rotate each of them by what angle?

Well, we start from the fact that we have 360° on a circle around a point.

See the Pen by thebabydino (@thebabydino) on CodePen.

We have six circles distributed evenly, so the rotation difference between any two consecutive ones is 360°/6 = 60°. Since we don't need to rotate the rightmost .circle (the second one), that one's at 0°, which puts the one before (the first one) at -60°, the one after (the second one) at 60° and so on.

See the Pen by thebabydino (@thebabydino) on CodePen.

Note that -60° and 300° = 360° - 60° occupy the same position on the circle, so whether we get there by a clockwise (positive) rotation of 300° or by going 60° the other way around the circle (which gives us the minus sign) doesn't matter. We'll be using the -60° option in the code because it makes it easier to spot a convenient pattern in our case.

So our transforms look like this:

.circle { &:nth-child(1 /* = 0 + 1 */) { transform: rotate(-60deg /* -1·60° = (0 - 1)·360°/6 */) translate($r); } &:nth-child(2 /* = 1 + 1 */) { transform: rotate( 0deg /* 0·60° = (1 - 1)·360°/6 */) translate($r); } &:nth-child(3 /* = 2 + 1 */) { transform: rotate( 60deg /* 1·60° = (2 - 1)·360°/6 */) translate($r); } &:nth-child(4 /* = 3 + 1 */) { transform: rotate(120deg /* 2·60° = (3 - 1)·360°/6 */) translate($r); } &:nth-child(5 /* = 4 + 1 */) { transform: rotate(180deg /* 3·60° = (4 - 1)·360°/6 */) translate($r); } &:nth-child(6 /* = 5 + 1 */) { transform: rotate(240deg /* 4·60° = (5 - 1)·360°/6 */) translate($r); } }

This gives us the distribution we've been after:

See the Pen by thebabydino (@thebabydino) on CodePen.

However, it's very repetitive code that can easily be compacted. For any of them, the rotation angle can be written as a function of the current index and the total number of items:

.circle { /* previous styles */ transform: rotate(calc((var(--i) - 1)*360deg/var(--nc))) translate($r); }

This works in WebKit browsers and Firefox 57+, but fails in Edge and older Firefox browsers due to the lack of support for using calc() inside rotate() functions.

Fortunately, in this case, we have the option of computing and setting the individual rotation angles in the Pug code and then using them as such in the Sass code:

- var nc = 6, ba = 360/nc; style .circle:nth-child(-n + #{.5*nc}) { background: #529ca0 } .watch-face - for(var i = 0; i < nc; i++) .circle(style=`--ca: ${(i - 1)*ba}deg`) .circle { /* previous styles */ transform: rotate(var(--ca)) translate($r); }

We didn't really need the previous custom properties for anything else in this case, so we just got rid of them.

We now have a compact code, cross-browser version of the distribution we've been after:

See the Pen by thebabydino (@thebabydino) on CodePen.

Good, this means we're done with the most important part! Now for the fluff...

Finishing up

We take the transform declaration out of the class and put it inside a set of @keyframes. In the class, we replace it with the no translation case:

.circle { /* same as before */ transform: rotate(var(--ca)) } @keyframes circle { to { transform: rotate(var(--ca)) translate($r) } }

We also add the @keyframes set for the pulsing animation on the .watch-face element.

@keyframes pulse { 0% { transform: scale(.15) rotate(.5turn) } }

Note that we don't need both the 0% (from) and 100% (to) keyframes. Whenever these are missing, their values for the animated properties (just the transform property in our case) are generated from the values we'd have on the animated elements without the animation.

In the circle animation case, that's rotate(var(--ca)). In the pulse animation case, scale(1) gives us the same matrix as none, which is the default value for transform so we don't even need to set it on the .watch-face element.

We make the animation-duration a Sass variable, so that, if we ever want to change it, we only need to change it in one place. And finally, we set the animation property on both the .watch-face element and the .circle elements.

$t: 4s; .watch-face { position: relative; animation: pulse $t cubic-bezier(.5, 0, .5, 1) infinite alternate } .circle { /* same as before */ animation: circle $t infinite alternate }

Note that we're not setting a timing function for the circle animation. This is ease in the original demo and we don't set it explicitly because it's the default value.

And that's it - we have our animated result!

We could also tweak the translation distance so that it's not exactly $r, but a slightly smaller value (something like .95*$r for example). This can also make the mix-blend-mode effect a bit more interesting:

See the Pen by thebabydino (@thebabydino) on CodePen.

Bonus: the general case!

The above is for six .circle petals in particular. Now we'll see how we can adapt it so that it works for any number of petals. Wait, do we need to do more than just change the number of circle elements from the Pug code?

Well, let's see what happens if we do just that:

The result for nc equal to 6 (left), 8 (middle) and 9 (right).

The results don't look bad, but they don't fully follow the same pattern - having the first half of the circles (the bluish green ones) on the right side of a vertical symmetry line and the second half (yellowish green) on the left side.

We're pretty close in the nc = 8 case, but the symmetry line isn't vertical. In the nc = 9 case however, all our circles have a yellowish green background.

So let's see why these things happen and how we can get the results we actually want.

Making :nth-child() work for us

First off, remember we're making half the number of circles have a bluish green background with this little bit of code:

.circle:nth-child(-n + #{.5*nc}) { background: #529ca0 }

But in the nc = 9 case, we have that .5*nc = .5*9 = 4.5, which makes our selector :nth-child(-n + 4.5). Since 4.5 is not an integer, the selector isn't valid and the background doesn't get applied. So the first thing we do here is floor the .5*nc value:

style .circle:nth-child(-n + #{~~(.5*nc)}) { background: #529ca0 }

This is better, as for a nc value of 9, the selector we get is .circle:nth-child(-n + 4), which gets us the first 4 items to apply a bluish green background on them:

See the Pen by thebabydino (@thebabydino) on CodePen.

However, we still don't have the same number of bluish green and yellowish green circles if nc is odd. In order to fix that, we make the circle in the middle (going from the first to the last) have a gradient background.

By "the circle in the middle" we mean the circle that's an equal number of circles away from both the start and the end. The following interactive demo illustrates this, as well as the fact that, when the total number of circles is even, we don't have a middle circle.

See the Pen by thebabydino (@thebabydino) on CodePen.

Alright, how do we get this circle?

Mathematically, this is the intersection between the set containing the first ceil(.5*nc) items and the set containing all but the first floor(.5*nc) items. If nc is even, then floor(.5*nc) and ceil(.5*nc) are equal and our intersection is the empty set ?. This is illustrated by the following Pen:

See the Pen by thebabydino (@thebabydino) on CodePen.

We get the first ceil(.5*nc) items using :nth-child(-n + #{Math.ceil(.5*nc)}), but what about the other set?

In general, :nth-child(n + a) selects all but the first a - 1 items:

See the Pen by thebabydino (@thebabydino) on CodePen.

So in order to get all but the first floor(.5*nc) items, we use :nth-child(n + #{~~(.5*nc) + 1}).

This means we have the following selector for the middle circle:

:nth-child(n + #{~~(.5*nc) + 1}):nth-child(-n + #{Math.ceil(.5*nc)})

Let's see what this gives us.

  • If we have 3 items, our selector is :nth-child(n + 2):nth-child(-n + 2), which gets us the second item (the intersection between the {2, 3, 4, ...} and {2, 1} sets)
  • If we have 4 items, our selector is :nth-child(n + 3):nth-child(-n + 2), which doesn't catch anything (the intersection between the {3, 4, 5, ...} and {2, 1} sets is the empty set ?)
  • If we have 5 items, our selector is :nth-child(n + 3):nth-child(-n + 3), which gets us the third item (the intersection between the {3, 4, 5, ...} and {3, 2, 1} sets)
  • If we have 6 items, our selector is :nth-child(n + 4):nth-child(-n + 3), which doesn't catch anything (the intersection between the {4, 5, 6, ...} and {3, 2, 1} sets is the empty set ?)
  • If we have 7 items, our selector is :nth-child(n + 4):nth-child(-n + 4), which gets us the fourth item (the intersection between the {4, 5, 6, ...} and {4, 3, 2, 1} sets)
  • If we have 8 items, our selector is :nth-child(n + 5):nth-child(-n + 4), which doesn't catch anything (the intersection between the {5, 6, 7, ...} and {4, 3, 2, 1} sets is the empty set ?)
  • If we have 9 items, our selector is :nth-child(n + 5):nth-child(-n + 5), which gets us the fifth item (the intersection between the {5, 6, 7, ...} and {5, 4, 3, 2, 1} sets)

Now that we can select the item in the middle when we have an odd number of them in total, let's give it a gradient background:

- var nc = 6, ba = 360/nc; style .circle:nth-child(-n + #{~~(.5*nc)}) { background: var(--c0) } | .circle:nth-child(n + #{~~(.5*nc) + 1}):nth-child(-n + #{Math.ceil(.5*nc)}) { | background: linear-gradient(var(--c0), var(--c1)) | } .watch-face(style=`--c0: #529ca0; --c1: #61bea2`) - for(var i = 0; i < nc; i++) .circle(style=`--ca: ${(i - 1)*ba}deg`)

The reason why we use a top to bottom gradient is that, ultimately, we want this item to be at the bottom, split into two halves by the vertical symmetry line of the assembly. This means we first need to rotate it until its x axis points down and then translate it down along this new direction of its x axis. In this position, the top of the item is in the right half of the assembly and the bottom of the item is in the left half of the assembly. So, if we want a gradient from the right side of the assembly to the left side of the assembly, this is a top to bottom gradient on that actual .circle element.

See the Pen by thebabydino (@thebabydino) on CodePen.

Using this technique, we have now solved the issue of the backgrounds for the general case:

See the Pen by thebabydino (@thebabydino) on CodePen.

Now all that's left to do is make the symmetry axis vertical.

Taming the angles

In order to see what we need to do here, let's focus on the desired positioning in the top part. There, we want to always have two circles (the first in DOM order on the right and the last in DOM order on the left) symmetrically positioned with respect to the vertical axis that splits our assembly into two halves that mirror each other.

See the Pen by thebabydino (@thebabydino) on CodePen.

The fact that they're symmetrical means the vertical axis splits the angular distance between them ba (which is 360° divided by the total number of circles nc) into two equal halves.

Angles formed by vertical symmetry line and the radial lines to the central points of the top angles are both equal to half a base angle (live).

So both are half a base angle (where the base angle ba is 360° divided by the total number of circles nc) away from the vertical symmetry axis, one in the clockwise direction and the other one the other way.

The upper half of the symmetry axis is at -90° (which is equivalent to 270°).

Degree values around the circle (live).

So in order to get to the first circle in DOM order (the one at the top on the right), we start from 0°, go by 90° in the negative direction and then by half a base angle back in the positive direction (clockwise). This puts the first circle at .5*ba - 90 degrees.

How to get the angle the first circle is placed at (live).

After that, every other circle is at the angle of the previous circle plus a base angle. This way, we have:

  • the first circle (index 0, selector :nth-child(1)) is at ca? = .5*ba - 90 degrees
  • the second circle (index 1, selector :nth-child(2)) is at ca? = ca? + ba = ca? + 1*ba degrees
  • the third circle (index 2, selector :nth-child(3)u) is at ca? = ca? + ba = ca? + ba + ba = ca? + 2*ba degrees
  • in general, the circle of index k is at ca? = ca??? + ba = ca? + k*ba degrees

So the the current angle of the circle at index i is .5*ba - 90 + i*ba = (i + .5)*ba - 90 degrees:

- var nc = 6, ba = 360/nc; //- same as before .watch-face(style=`--c0: #529ca0; --c1: #61bea2`) - for(var i = 0; i < nc; i++) .circle(style=`--ca: ${(i + .5)*ba - 90}deg`)

This gives our final Pen, where we only need to change nc from the Pug code to change the result:

See the Pen by thebabydino (@thebabydino) on CodePen.

Simplifying the Apple Watch Breathe App Animation With CSS Variables is a post from CSS-Tricks

New flexbox guides on MDN

Fri, 01/12/2018 - 9:37am

MDN released a comprehensive guide to Flexbox with new and updated materials by Rachel Andrew. The guide includes 11 posts demonstrating layouts, use cases and everything you could possibly want or need to know on the topic. All of the related Flexbox properties are nicely and conveniently attached to the table of contents, making this extremely easy to use.

In this post, Rachel adds helpful thoughts and context about Flexbox. Her comment on Flexbox initially being treated as a silver bullet solution for all our layout issues struck me:

Prior to Grid shipping, Flexbox was seen as the spec to solve all of our layout problems, yet a lot of the difficulty in using Flexbox is when we try to use it to create the kind of two-dimensional layouts that Grid is designed for. Once again, we find ourselves fighting to persuade a layout method to do things it wasn’t designed to do.

Guilty as charged. I remember being so eager to ditch floats and learn a new syntax that I treated Flexbox as a square peg trying to be fit into a round hole. That definitely bit me on at least one project.

Most importantly about this guide is that it forms a sort of trifecta of reference materials on layout specifications provided by CSS: Flexbox, Grid and other Box Alignment properties.

Oh, and while we're on the topic, we have Flexbox and Grid guides right here on CSS-Tricks. You can never learn too much, right?

Direct Link to ArticlePermalink

New flexbox guides on MDN is a post from CSS-Tricks

Third-Party Scripts

Fri, 01/12/2018 - 4:55am

Trent Walton:

My latest realization is that delivering a performant, accessible, responsive, scalable website isn’t enough: I also need to consider the impact of third-party scripts. No matter how solid I think my prototype is, it doesn’t absolve me from paying attention to what happens during implementation, specifically when it comes to the addition of these third-party scripts.

I recently had a conversation with a friend working on quite a high profile e-commerce site. They were hired to develop the site, but particularly with performance in mind. They were going the PWA route, but were immediately hamstrung by third-party scripts. One of them, apparently unavoidably, couldn't be HTTPS, meaning the site was immediately disqualified from being a PWA. They could still do a good job in many other areas, but right and left their great performance work was slaughtered by third-party scripts. I don't envy being in that position.

It's often the fault of "tag managers." There are a bunch of them out there. Here's a marketing pitch for one of them:

Marketers want tag management that’s simple, reliable, and integrates easily with existing systems ... You’ll launch programs faster, so you can make swifter decisions.

In other words, "Give your marketing team the ability to add whatever third-party JavaScript they want quickly without having to go through your normal deployment process." I can understand why they are needed in some organizations, but it still sends chills up my spine.

Third-party scripts could conceivably be a part of a design style guide. Right alongside your buttons and modals could be a list of the third-party scripts in place on a site. Brad Frost:

The idea is that someone (or as Trent points out, some *thing*) could hypothetically crawl through all the included scripts on a site, and display them in the in style guide alongside all the color swatches, icons, UI components, etc. After all, they affect the end user experience just as much (if not more) than all those other design elements. You can visually weight them based on how gnarly they are and thus have thoughtful conversations with your team — especially those folks are carelessly chucking in all these performance-damning scripts — about the pros and cons of each script that gets included.

Third-party scripts are probably the #1 cause of poor performance and bad UX on the web. It's no wonder things like AMP exist. The fact that it disallows third-party scripts is probably the largest contributor to it making sites fast. Controversial as hell, though, in its other choices.

As fate would have it, third-party JavaScript is even more dangerous than it ever has been, thanks to Spectre and Meltdown. Jorgé:

Q: Is JavaScript vulnerable in my browser?
A: Yes, browsing a web can give access to third parties to your machine's memory beyond the browser.


More on Third-Party JavaScript

If you, like Trent, are planning to bone up on your third-party JavaScript chops, here's a bunch of stuff from other developers in the past few years digging into it all. Some of this is targeted at you being the deliverer of the third-party JavaScript.

Third Party JavaScript (In the Third Person) Slides by Alex Sexton Presentation slide

View Presentation

On Third-Party Javascript - The Principles by Gergely Nemeth

When serving third-party JavaScript applications the size of it and the cache policy are crucial, as both not just affect the time your users have to wait to see the application, but also your monthly bills.

See also: Writing third-party Javascript the integration part in a nutshell.

Read Post

Third-Party Javascript by Ben Vinegar and Anton Kovalyov

amzn_assoc_tracking_id = "csstricks-20"; amzn_assoc_ad_mode = "manual"; amzn_assoc_ad_type = "smart"; amzn_assoc_marketplace = "amazon"; amzn_assoc_region = "US"; amzn_assoc_design = "enhanced_links"; amzn_assoc_asins = "1617290548"; amzn_assoc_placement = "adunit"; amzn_assoc_linkid = "5b25672b1eb04d67cf22c6b254ad7924";

Things to Know (and Potential Dangers) with Third-Party Scripts by Yaphi Berhanu

The web is full of third-party scripts. Sites use them for ads, analytics, retargeting, and more. But this isn't always the whole story. Scripts can track your behavior, your preferences, and other information.

Read Post

I’m harvesting credit card numbers and passwords from your site. Here’s how. by David Gilbertson

My goal is simply to point out that any site that includes third party code is alarmingly vulnerable, in a completely undetectable way.

Read Post

Ain't No Party Like A Third-Party JS Party by Rebecca Murphey

You thought you had the hang of this whole JavaScript thing, but now you're in the world of third-party JavaScript, where all you control is a single script tag and where it's all but impossible to dream up every hostile environment in which your code will be expected to work. "It works on my machine" has never rung quite so hollow. In this talk, we'll take a look at some of the delightful bugs we've had to solve at Bazaarvoice while working on the third-party JavaScript app that collects and displays ratings and reviews for some of the world's largest retailers.

Watch Video

(Subscription required)

3rd Party Javascript Management Cheat Sheet

The invocation of 3rd party JS code in a web application requires consideration for 3 risks in particular:

  1. The loss of control over changes to the client application,
  2. The execution of arbitrary code on client systems,
  3. The disclosure or leakage of sensitive information to 3rd parties.

Read Post

Third-Party Scripts is a post from CSS-Tricks

Small Tweaks That Can Make a Huge Impact on Your Website’s Accessibility

Thu, 01/11/2018 - 7:33am

For a beginner, accessibility can be daunting. With all of the best intentions in the world, the learning curve to developing compliant, fully accessible websites and apps is huge. It's also hard to find the right advice, because it's an ever-changing and increasingly crowded landscape.

I've written this post to give you some tips on small things that can make a big difference, while hopefully not affecting your development process too much.

Let's dive in!

Document Structure and Semantics

It probably doesn't come as much of a surprise that structuring your HTML in an organized, semantic way will make a big difference. Screen readers rely on a well-structured document in order to follow a coherent narrative, so make sure that you're using the elements that the HTML5 spec provides responsively and effectively.

If you’re unsure about how to markup your work correctly, check out resources such as HTML5 Doctor, Code Academy and of course, CSS-Tricks. You can also check out articles like “Writing HTML with accessibility in mind” and “Semantic Structure” to get you going in the right direction.

Let's look at three specific things that can help ensure a well-structured and semantic document.

Use a Single <main> Element

A good example of building a responsible, semantic document structure is only using one <main> element. This should serve as a signpost for the most important content of the page for your user.

Add an ID to it and offer a skip link in your main <header> like so:

<header role="banner"> <h1>Your main page title</h1> <a href="#main-content">Skip to the main content</a> </header> <!-- Further down the document --> <main id="main-content"> <!-- Put your main body of content in here and other really important stuff --> </main>

This little trick should help your screen reader users out in a big way, because they can go ahead and skip the fancy bits and dive right into your important content. It’s also great for keyboard users for the same reason.

Another nice touch is to add a :focus style to the skip link that makes it visible. Try pressing your tab key on GitHub.com. Pretty neat, right?

Use Elements Appropriately

So, <button> elements are a pain in the butt to style right? That doesn’t mean you should attach your JavaScript events to a <div> or an <a href="#"> though. You see, when you use a <button>, you get keyboard events for free. You’re also helping screen reader users out because it’ll announce the element correctly. Check out this example:

document.getElementsByTagName('button')[0].addEventListener('click', evt => { alert('Oh, hey there!'); });

If a user focused on that button and hit the enter key, that event would fire. That makes both yours and the users' lives a bit easier. Well worth it, right?

See the Pen Button click example by Andy Bell (@hankchizljaw) on CodePen.

Get Your Heading Hierarchy Locked-Down

It's really common for screen reader users to navigate a page by using the heading structure. That means we should help them out and create a nice hierarchy for them. Let's take a look at a standard blog post:

<main id="main-content"> <article> <!-- The page title is up in the main <header> in this instance --> <h2>My awesome blog post</h2> <p>Vestibulum id ligula porta felis euismod semper.</p> <p>Vestibulum id ligula porta felis euismod semper.</p> <h3>A sub-section of this post</h3> <p>Vestibulum id ligula porta felis euismod semper.</p> <h4>A sub-section of the sub-section</h4> <p>Vestibulum id ligula porta felis euismod semper.</p> </article> </main>

With that sample, the user can navigate to the start of "My awesome blog post" and then have the ability to skip to sub-sections and nested sub-sections easily. They can also skip back up. It's just a nice way of helping them consume the content you've produced as easily as possible.

It can be recommended that a page has a single <h1> element, even though the W3C HTML5 spec says you can have many. I personally agree with the use of a single <h1>, but you can have many, as long as you follow a nice structure and hierarchy. That's the key here.

Get Your Color Contrast Right

To be WCAG 2.0 AA compliant, you need to have a contrast ratio of 4.5:1 for normal text. This is your paragraphs, buttons, navigation, etc. You need to go for a ratio of 3:1 for larger text, such as headings. I'd say this should be your minimum as it's incredibly achievable with tools such as Tota11y, Contrast and the WebAim contrast checker. You can still get plenty of color balance and variation in your design too.

The reason that contrast is so important is because there's so much variation in environment that you probably don't even consider, such as bright sunlight and poor quality displays. Add this to a visual impairment or, say, a migraine and you're potentially causing problems for your users.

Getting the contrast right will have a huge, positive effect across a wide spectrum of your users.

Responsible Text Labels

We’ve all built out a list of items with a non-descriptive, but visually appealing "More" button, right? More what though? We need to be more responsible with this and provide some context.

One way to achieve this is by visually hiding descriptive text with CSS and hiding the non-descriptive text from screen readers. It’s tempting to use display: none;, but screen readers can ignore elements with that set, so we need to be more creative. I use something like this little helper:

.visually-hidden { display: block; height: 1px; width: 1px; overflow: hidden; clip: rect(1px 1px 1px 1px); clip: rect(1px, 1px, 1px, 1px); clip-path: inset(1px); visibility: hidden; white-space: nowrap; position: absolute; }

With this CSS in place, we can do something like this:

<a href="/link-to-your-page"> <!-- This is hidden from a screen reader, but visible visually --> <span aria-hidden="true">More</span> <!-- This is visible to a screen reader, but visually hidden --> <span class="visually-hidden">Continue reading: "Your post title here"</span> </a>

A sighted user will only see “More” and a screen reader user will hear “Continue reading: 'Your post title here.'" Both sets of users are happy.

You can also achieve the above by using an aria-label on the <a> tag. This will override the text within for a screen-reader:

<a href="/link-to-your-page" aria-label="Continue reading: 'Your post title here'"> More </a> Small Typography Tweaks With a Big Impact

It's always worth remembering that people with a visual impairment or learning difficulty could be trying to read your content, so some small tweaks to your typography can go a long way.

A body of content such as an article should be sized at 16px (or equivalent unit) at a minimum. It's also worth increasing your line-height to around 1.5 too. Space between lines can help readers with dyslexia to understand your content better. The combination of size and space is also great for older people and/or short-of-sight people. Even small summaries and aside content should be at least 12px (or equivalent unit). Anything smaller than that will alienate users who struggle to read.

Another trick is to highlight key words and phrases if your content is quite complex. This not only benefits users who are slightly slower at processing content but it also helps people who like to scan over an article, like I do.

Lastly on this section, I'd advise you to be careful with your font choices. Fonts with complex ligatures and decorative elements can be really distracting, so maybe limit the usage of those to key, large headings only. It's also been advised that sans-serif fonts are better for readers with dyslexia. Check out this article for more on that and other text formatting tips.

Enhance Keyboard Support

There are a few little tweaks you can do to help users who primarily use their keyboard to navigate your website.

Say you've got a little button that shows a dialogue when you click it. You should attach an event to the escape key that hides it. Here's a sample snippet:

document.addEventListener('keyup', (evt) => { if(evt.keyCode === 27) { // Run whatever code hides your dialogue } });

See the Pen Escape key demo by Andy Bell (@hankchizljaw) on CodePen.

Another tweak you can do for our keyboard-navigating buddies is not hiding focus from them. Browsers give us focus states for free with outline. I know it can look ugly, but hot-damn it’s useful for keyboard users. If you want to get rid of that blue glow, I get it—just please use the :focus pseudo selector to add an obvious state change to it instead. Here's a sample:

.your-element { background: red; } .your-element:focus { outline: none; /* Reset the default */ box-shadow: 0 0 0 3px black; /* A very obvious state change */ } Don't Rely on Color Alone to Communicate State Changes

Let’s end on a really important one. Color shouldn’t be relied upon alone to communicate state changes. Take this scenario as an example:

You’ve got a button that posts a form. You wrote some neat JavaScript that makes it go grey while it sends the data. It then either turns green or red, depending on what the status is.

For a colorblind user, this is a nightmare. To them, the button may have barely changed enough for them to notice, so they may just keep clicking and clicking while getting really frustrated. This isn’t ideal.

So, instead of relying on color, let’s enhance that with a status message that supports the button’s state on response.

See the Pen Enhanced state change communication demo by Andy Bell (@hankchizljaw) on CodePen.

That sample is a great way to quickly communicate to the user that something has changed and the use of color, text and iconography clearly communicates that change. Disabling the button whilst the response is processed is also a great help to the user.

Wrapping Up

These little tips should make a big difference to your users, and I hope you dive into your projects and implement some of them.

You should also keep learning about accessibility. I recommend following people such as Heydon Pickering, Scott O’Hara, Laura Kalbag, and Rob Dobson on Twitter. I also recommend that you check out resources such as Inclusive Components and the A11y Project.

The greater your knowledge gets, the better your websites and products will be for a much wider audience. That can only be a good thing, right?

Small Tweaks That Can Make a Huge Impact on Your Website’s Accessibility is a post from CSS-Tricks

?Incapsula’s Global DDoS Threat Landscape Report

Thu, 01/11/2018 - 7:32am

(This is a sponsored post.)

The newly released Q3 2017 Global DDoS Threat Landscape Report features insights on attacks and mitigation. These are some of the key findings:

  • Bitcoin was one of the most targeted industries
  • High packet rate attacks grew more common
  • A third of network layer attacks were highly persistent
  • Botnet activity out of India and Turkey continued to climb

Learn about the top attacked countries, industries, and vectors here and how to protect your site with Incapsula.

Direct Link to ArticlePermalink

?Incapsula’s Global DDoS Threat Landscape Report is a post from CSS-Tricks

HTML 5.2 is Done, HTML 5.3 is Coming

Wed, 01/10/2018 - 9:48am

The W3C has completed its second round of HTML5 recommendations for implementation. The entire announcement is worth a read because there are interesting tidbits that provide more context and personnel changes within W3C, but the highlights of this recommendation are nicely summed up:

Many of the features added integrate other work done in W3C. The Payment Request API promises to make commerce on the Web far easier, reducing the risks of making a mistake or being caught by an unscrupulous operator. New security features such as Content Security Policy protect users more effectively, while new work incorporated from ARIA helps developers offer people with disabilities a good user experience of their applications.

There are also semantic changes to HTMl elements that are worth noting:

Clarifications and bug fixes bring the HTML Recommendation closer to what has been deployed recently. The definition for the main element has been updated to support modern responsive design patterns, the style element can be used inside the body element. Numerous constraints on code have been loosened, while where necessary for interoperability or security a few have been carefully reinforced.

And, spoiler alert! HTML 5.3 is officially in its first public working draft.

Direct Link to ArticlePermalink

HTML 5.2 is Done, HTML 5.3 is Coming is a post from CSS-Tricks


Wed, 01/10/2018 - 9:48am

Here’s an interesting and super useful Chrome extension by Nitin Tulswani that measures React component performance:

React Performance Devtool is a browser extension for inspecting the performance of React Components. It statistically examines the performance of React components based on the measures which are collected by React using window.performance API. Along with the browser extension, the measures can also be inspected in a console.

Also, if you’re interested in learning more about the process of this tool, there’s a great thread that digs into the history of the project.

Direct Link to ArticlePermalink

react-perf-devtool is a post from CSS-Tricks

The latest ways to deal with the cascade, inheritance and specificity

Wed, 01/10/2018 - 4:24am

The cascade is such an intrinsic part of CSS that they put it right there in the name. If you’ve ever needed to use !important to affect specificity in the cascade, you’ll know that it can be a tricky thing to deal with. In the early days of CSS, it was common to see highly specific selectors like this:

#sidebar ul li {}

We’re all much better at managing specificity nowadays. It’s a widely accepted best practice to keep specificity low and flat—to shun ID selectors, to make liberal use of classes, and to avoid unnecessary nesting. But there are still plenty of situations where a more specific selector will be useful. With the introduction of a newly proposed pseudo-class, more support of the shadow DOM, and the use of the all property, we will soon be able to handle inheritance and specificity in new and exciting ways.

The :is Pseudo-Class

Lea Verou recently proposed this new pseudo-class specifically designed to control specificity. It’s already made its way to the CSS Level 4 Selectors spec. Lea has a write up of why it’s useful and there’s some coverage of it in the CSS-Tricks almanac.

Let’s take :not as an example. The specificity of :not is equal to the specificity of its argument. This makes using :not rather painful. Take the following as an example:

See the Pen :not and specificity by CSS-Tricks (@css-tricks) on CodePen.

We might expect that the .red class would have higher specificity because it is lower in the cascade. However, for any styles to override div:not(.foobar) they would need to at least match the specificity of a combined element selector (div) and class selector (.foobar). Another approach would be div.red, but there is a better way. This is where :is can help.

div:is(:not(.foobar)) { background-color: black; }

The :not selector no longer adds any specificity, so the total specificity of the above selector is simply that of one element selector (div). The .red class would now be able to override it in the cascade. Once implemented, specificity hacks will be a thing of the past.

Shadow DOM

Today, many people are using classes in HTML like this:

<form class="site-search site-search--full"> <input type="text" class="site-search__field"> <button type="Submit" class="site-search__button">search</button> </form>

When using shadow DOM, rather than following a verbose naming convention, we’ll be able to omit classes altogether. Styles defined within the shadow DOM are scoped to apply only within the component. Styling can be achieved with simple element selectors without worrying about whether the selectors will interfere with elements elsewhere on the page.

See the Pen shadow dom by CSS GRID (@cssgrid) on CodePen.

It’s liberating to write such easy CSS. No more effort spent naming things. Shadow DOM looks like it is finally making its way to full browser support. It's likely to make it into the next release of Firefox while Edge have implementation as a high priority.

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

DesktopChromeOperaFirefoxIEEdgeSafari5340NoNoNoTPMobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox11.0-11.2NoNo6262No The all Property

The all property is a way of setting all CSS properties at once—everything from align-content to z-index. What values does it accept? I can’t think of any use case when I’d want all properties to inherit, but that’s an option. Then there’s initial which is more like applying a CSS reset where all the styles are gone. No padding. No margin. The initial value is set per property, regardless of the element it is applied to. The initial value of display is inline, even if you apply it to a div. The font-style of an em tag is normal, as is the font-weight of a strong tag. Link text will be black. You get the idea. (You can find the initial value of any CSS property on MDN.) This does perhaps limit its usefulness, going further than we might like by removing all styles, regardless of context.

See the Pen all: initial by CSS GRID (@cssgrid) on CodePen.

Sadly, the most useful value for all is also the least widely implemented: revert. It can remove the styles that you as a developer have applied, while leaving the default user-agent styles intact. We’ve all seen a page of HTML without a stylesheet—black Times New Roman on a white (transparent) background with blue underlined links. If you really want to avoid inheritance, then all: revert has you covered. All divs will be display: block and spans will be inline. All em tags will be italic and strong tags will be bold. Links will be blue and underlined.

See the Pen all: revert by CSS GRID (@cssgrid) on CodePen.

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

DesktopChromeOperaFirefoxIEEdgeSafariNoNoNoNoNo9.1Mobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox9.3NoNoNoNoNo The future?

CSS-in-JS is a cry for help. We at @csswg should pay attention to this and address the issues before it gets worse.https://t.co/lWQ4ct61ir

— Lea Verou (@LeaVerou) May 24, 2017

The miscellany of rival unstandardized methods for writing CSS-in-JS was an attempt to sidestep these same issues. That approach has gained popularity over the last several years. Some of its proponents have deemed inheritance, the cascade and specificity as fundamentally flawed design decisions of the language. The CSS Working Group at the W3C is responding by improving the power of CSS and the native web platform. It will be interesting to see the outcome…

The latest ways to deal with the cascade, inheritance and specificity is a post from CSS-Tricks

Making CSS Animations Feel More Natural

Tue, 01/09/2018 - 5:59am

It used to be that designers designed and coders coded. There was no crossover, and that’s the way it was. But with the advent of CSS transitions and animations, those lines are blurring a bit. It’s no longer as simple as the designer dictating the design and the coder transcribing—designers must now know something about code, and coders must know something about design in order to effectively collaborate.

As an example, let’s say a designer asks a developer to make a box bounce. That’s it—no additional instruction. Without some cross-knowledge and a common vocabulary, both sides are a little lost in this communication: the developer doesn’t have enough information to fully realize the designer’s vision, but the designer doesn’t really know what the options are and how to communicate them. With a very basic interpretation, you might end up with something that looks like this:

See the Pen Bouncing Box 1 by Brandon Gregory (@pulpexploder) on CodePen.

Not very exciting. Although, to be fair, this does meet all of the criteria given. We can definitely do better than this, though.

The first thing to look at is the timing function. In the above example, we’re using a linear timing function, which means that the box is constantly moving at the same speed. In some cases, this is desirable; however, in the real world, motion usually doesn’t work like that.

An easy fix is to simply change the timing function to ease. This makes the beginning and ending of each animation a little slower than the middle part, which adds a more natural look to some animations. Here’s the box with the easing function turned on:

See the Pen Bouncing Box 2 by Brandon Gregory (@pulpexploder) on CodePen.

This is a slight improvement, but there’s still a lot of work to be done. The box still looks mechanical and stiff, with the same animation occurring in the same timeframe over and over. Adding a slight delay between bounces adds some visual contrast that seems a little more natural:

See the Pen Bouncing Box 3 by Brandon Gregory (@pulpexploder) on CodePen.

The box now looks like it’s jumping rather than simply moving up and down. There’s a little wind-up and cool-down between jumps that mimics what a live creature might do if given the same instruction. Even though we have no reference for what a jumping box would look like, we all have a pretty good idea of what a jumping creature would look like. Because we know what would happen in nature, by mimicking that, the animation feels more natural. But we can do more to make that wind-up feel a little more weighty.

If you watch cartoons, you’ll notice that natural movements are often exaggerated, creating a caricature of real life. When done well, this can feel just as natural as something in the real world, with the added bonus of infusing a little charm and character into the animation.

At this stage, collaboration between the designer and developer is crucial?—?but many designers may not even be aware that these options exist. It may be up to the developer to pitch this possibility to the designer.

By adding some subtle distortion to the scale of the box, we can add a lot to the animation:

See the Pen Bouncing Box 4 by Brandon Gregory (@pulpexploder) on CodePen.

Now, the box has character. It feels alive. There are many things to tweak, but this is already moving much farther than the original instruction?—?in a very good way!

We’re going to go a step further and add a little rebound at the end of the jump:

See the Pen Bouncing Box 5 by Brandon Gregory (@pulpexploder) on CodePen.

The second bounce is making this feel more alive, but something still seems off. The bounce looks stiff compared to the rest of the animation. We need to add another bit of distortion like we did for the wind-up:

See the Pen Bouncing Box 6 by Brandon Gregory (@pulpexploder) on CodePen.

That subtle distortion at the end makes the rebound seem much more natural. Overall, a huge improvement from our basic linear bounce in the first example.

That right there may be exactly what we’re looking for, but further tweaks to the rate of movement can be made with a custom cubic Bézier curve:

See the Pen Bouncing Box 7 by Brandon Gregory (@pulpexploder) on CodePen.

Without both the designer and the developer aware of basic animation principles and controls, this level of customization is impossible. Really, this article just scratches the surface of both fields. If you’re a web designer or a web developer who works with designers, I’d strongly urge you to read up on both.

For animation principles, The Illusion of Life: Disney Animation by Ollie Johnston and Frank Thomas is a great primer on how to make that caricature of real life seem alive and real. With that common language in place, communication and collaboration between designers and developers becomes much easier.

amzn_assoc_tracking_id = "csstricks-20"; amzn_assoc_ad_mode = "manual"; amzn_assoc_ad_type = "smart"; amzn_assoc_marketplace = "amazon"; amzn_assoc_region = "US"; amzn_assoc_design = "enhanced_links"; amzn_assoc_asins = "0786860707"; amzn_assoc_placement = "adunit"; amzn_assoc_linkid = "26ac1508fd6ec7043cb51eb46b883858";

For the technical controls and variations of CSS animation, the possibilities are nearly endless. Delay and timing are simple to adjust. As mentioned, if you don’t like the out-of-the-box ease timing function, it’s very possible to create your own using a cubic-bezier(). You can also adjust the level of distortion you want to bring the animation closer to or further from reality. The important thing is that both the designer and developer are thinking about these variations rather than blindly taking everything without customization. Shared knowledge and collaboration can make even simple animations into great ones.

More Resources

Making CSS Animations Feel More Natural is a post from CSS-Tricks

WordPress User Survey Data for 2015-2017

Mon, 01/08/2018 - 10:54am

A grand total of 77,609 responses from WordPress users and professionals collected by Automattic between 2015 and 2017. The stats for 2015 and 2016 have been shared at the annual State of the Word address and 2017 marks the first time they have been published on WordPress News.

A few items that caught my attention at first glance:

  • Between 66% and 75% of WordPress users installed WordPress on their own. In other words, they were savvy enough to do it without the help of a developer. Hosting providers were next up and clocked in at 13-14% of installs.
  • WordPress professionals described their clients as large and enterprise companies only 6-7% of the time. I guess this makes sense if those companies are relying on in-house resourcing, but I still would have pegged this higher.
  • What do users love most about WordPress? It's simple and user-friendly (49-52%). What frustrates them most about it? Plugins and themes (19-28%). Seems like those two would go hand-in-hand to some degree.

I'm not a statistician and have no idea how much the results of these surveys accurately reflect the 26% of all sites on the internet that are powered by WordPress, but it sure is interesting.

Direct Link to ArticlePermalink

WordPress User Survey Data for 2015-2017 is a post from CSS-Tricks

©2003 - Present Akamai Design & Development.