Web Standards

The Fragmented, But Evolving State of CSS-in-JS

Css Tricks - Thu, 12/20/2018 - 4:43am

TLDR: The CSS-in-JS community has converged on a consistent API.

Not so long ago, a Facebook engineer compiled a list of the available CSS-in-JS methodologies. It wasn’t short:

aphrodite, babel-plugin-css-in-js, babel-plugin-pre-style, bloody-react-styled, classy, csjs, css-constructor, css-light, css-loader, css-ns, cssobj, cssx-loader, cxs, electron-css, emotion, es-css-modules, freestyler, glamor, glamorous, hiccup-css, hyperstyles, i-css, j2c, jsxstyle, linaria, nano-css, pre-style, radium, react-css-builder, react-css-components, react-css-modules, react-cssom, react-fela, react-free-style, react-inline-css, react-inline-style, react-inline, react-jss, react-look, react-native-web, react-statics-styles, react-styl, react-style, react-styleable, react-stylematic, react-theme, react-vstyle, reactcss, restyles, scope-styles, smart-css, stile-react-media-queries, stilr, stylable, style-it, styled-components, styled-jsx, styletron-react, styling, superstyle, typestyle, uranium

Such a fragmented ecosystem was far from appealing. Which one should you pick, (if any)?

Contributing to Javascript fatigue — you need at most one. Also feel free to not learn any.

GitHub stars are one useful metric:

However, GitHub stars say nothing about a project’s trajectory — perhaps they were accumulated long ago and the repo has since fallen out of favor or is no longer maintained. Glamor has plenty of open issues, and hasn’t seen a commit in over a year. Its author advises:

...it mostly works, I'm not going to do any major changes… if you need something more modern, I'd recommend emotion, it mostly matches glamor's api, and is actively maintained.

The similarly named Glamorous was recently deprecated with its author also recommending users switch to Emotion:

At the time, Emotion had some features that Styled Components didn’t. Since then, Styled Components has made some big announcements.

Styled Components sells itself as the CSS-in-JS library for people that *like* CSS. Styled Components gained popularity by utilizing tagged template literals — allowing developers to *just write CSS* in the same syntax they already know, but inside JavaScript files. While this has proven popular, some developers prefer to [write styles as JavaScript objects. Emotion offered flexibility — developers could choose how to write their styles. Styled Components eventually followed suit.

styled-components v3.3.0 is out with first-class object support! 😍

Lots of people have been asking for this, your wishes have been heard! Shoutout to @probablyup for taking care of this release.

👉 https://t.co/yOHWg78nF4 pic.twitter.com/Ic8fZdAFVs

— Max Stoiber (@mxstbr) May 25, 2018

Emotion also offers a css prop, which Styled Components didn’t have, until…

🎉 Announcing support for the css prop in styled-components! 🎉

This has been a long time coming, hope y'all enjoy! ✨

👉 https://t.co/DMdrG6uviZ

Huge shoutout to @satya164 for coming up with the ingenious implementation! 👏

— Max Stoiber (@mxstbr) November 26, 2018

The rival CSS-in-JS libraries have stolen from each other until landing upon the same feature set and the same syntax — Emotion and Styled Components have an almost identical API. What once felt like a total mess of competing methodologies and libraries now feels somewhat stable. Even if CSS-in-JS hasn’t standardized on a dependency, it now has standardized a way of doing things — they’re just implemented differently:

Internally, quite a bit. SC has a lot of complexity around organizing style tag order.
Re css prop: SC requires Babel plugin and uses the entire SC custom component creation. Emotion will skip the custom component if it can and just renders the element with the className directly

— Kye Hohenberger (@tkh44) December 7, 2018

Styled Components is by far the most popular CSS-in-JS library, but Emotion has seen a rapid increase in usage.

Both are used by some major companies. Styled Components are utilized by plenty of large companies, including Bloomberg, Atlassian, Reddit, Target, BBC News, The Huffington Post, Coinbase, Patreon, Vogue, Ticketmaster, Lego, InVision and Autodesk just to name a few.

Emotion boasts fewer recognizable names, but has been recently adopted by the New York Times.

Great article about the launch of our new Story designs on the NYT today. It mentions our Shared Components initiative - would have been impossible without Emotion / CSS-in-JS. Absolute game-changer. Living in the future. https://t.co/pZLDJjsbEr

— Scott Taylor (@wonderboymusic) May 8, 2018

While these libraries certainly do seem to be most popular amongst React users, they can be used with other frameworks. While they seem to have converged on the same features at last, it’s difficult to say whether this is the end point of CSS-in-JS, or whether we’ll see a continued evolution from here.

The post The Fragmented, But Evolving State of CSS-in-JS appeared first on CSS-Tricks.

WooCommerce

Css Tricks - Thu, 12/20/2018 - 4:27am

(This is a sponsored post.)

I just read a nicely put together story about WooCommerce over on the CodeinWP blog. WooCommerce started life as WooThemes, sort of a "premium themes" business started by just a couple of fellas who had never even met in person. Two years and a few employees later they launch WooCommerce, and 2 years after that it hits a million downloads. A major success story, to be sure, but a collaborative and remote-work based one that wasn't exactly overnight. Another 2 years and Automattic picks them up and the WooThemes part is spun down.

Now we're 3-4 years into WooCommerce being an Automattic project and it's looking at nearly 60 million downloads, 4 million of which are active. A number they are saying is about 30% of all eCommerce on the web. Daaaaang. I've used WooCommerce a number of times and it always does a great job for me.

Direct Link to ArticlePermalink

The post WooCommerce appeared first on CSS-Tricks.

All the Small Things: How Not To Annoy Your Mobile Users

Usability Geek - Wed, 12/19/2018 - 1:00pm
Let us talk about Peter. He has just bought a great shirt. It is on trend. The feel, and the price point was a bargain. He gets home, and it feels great. But then. It starts with a tickle, then a...
Categories: Web Standards

Fighting FOIT and FOUT Together

Css Tricks - Wed, 12/19/2018 - 4:30am

Lots from Divya with the setup:

There are 2 kinds of problems that can arise when using webfonts; Flash of invisible text (FOIT) and Flash of Unstyled Text (FOUT) ... If we were to compare them, FOUT is of course the lesser of the two evils

If you wanna fight FOIT, the easiest tool is the font-display CSS property. I like the optional value because I generally dislike the look of fonts swapping.

If you want to fight them both, one option is to preload the fonts:

<link rel="preload" href="/fonts/awesome-l.woff2" as="font" />

But...

Preload is your friend, but not like your best friend ... preloading in excess can significantly worsen performance, since preloads block initial render.

Just like CSS does.

In a conversation with Scott Jehl, he pointed out to me that "preloads block initial render" isn't quite true, and he put together a test case. A <link rel="preload" ...> resource doesn't block rendering in and of itself.

Even huge sites aren't doing much about font loading perf. Roel Nieskens:

I expected major news sites to be really conscious about the fonts they use, and making sure everything is heavily optimised. Turns out a simple Sunday afternoon of hacking could save a lot of data: we could easily save roughly 200KB

Fonts are such big part of web perf, so let's get better at it! Here's Zach Leatherman at the Performance.now() conference:

Part of the story is that we might just have lean on JavaScript to do the things we need to do. Divya again:

Web fonts are primarily CSS oriented. It can therefore feel like bad practice to reach for JavaScript to solve a CSS issue, especially since JavaScript is a culprit for an ever increasing page weight.

But sometimes you just have to do it in order to get what you need done. Perhaps you'd like to handle page visibility yourself? Here's Divya's demonstration snippet:

const font = new fontFace("My Awesome Font", "url(/fonts/my-awesome-font.woff2)" format('woff2')") font.load().then (() => { document.fonts.add(font); document.body.style.fontFamily = "My Awesome Font, serif"; // we can also control visibility of the page based on a font loading // var content = document.getElementById("content"); content.style.visibility = "visible"; })

But there are a bunch of other reasons. Zach has documented them:

  • Because, as you load in fonts, each of them can cause repaints and you want to group them.
  • Because the user has indicated they want to use less data or reduce motion.
  • Because you'd like to be kind to slow networks.
  • Because you're using a third-party that can't handle font-display.

The post Fighting FOIT and FOUT Together appeared first on CSS-Tricks.

Google Fonts and font-display

Css Tricks - Wed, 12/19/2018 - 4:26am

The font-display descriptor in @font-face blocks is really great. It goes a long way, all by itself, for improving the perceived performance of web font loading. Loading web fonts is tricky stuff and having a tool like this that works as well as it does is a big deal for the web.

It's such a big deal that Google's own Pagespeed Insights / Lighthouse will ding you for not using it. A cruel irony, as their own Google Fonts (easily the most-used repository of custom fonts on the web) don't offer any way to use font-display.

Summarized by Daniel Dudas here:

Google Developers suggests using Lighthouse -> Lighthouse warns about not using font-display on loading fonts -> Web page uses Google Fonts the way it's suggested on Google Fonts -> Google Fonts doesn't supports font-display -> Facepalm.

Essentially, we developers would love a way to get font-display in that @font-face block that Google serves up, like this:

@font-face { font-family: "Open Sans Regular"; src: url("..."); font-display: swap; }

Or, some kind of alternative that is just as easy and just as effective.

Seems like query params is a possibility

When you use a Google Font, they give you a URL that coughs up a stylesheet and makes the font work. Like this:

https://fonts.googleapis.com/css?family=Roboto

They also support URL params for a variety of things, like weights:

https://fonts.googleapis.com/css?family=Open+Sans:400,700

And subsets:

http://fonts.googleapis.com/css?family=Creepster&text=TRICKS https://fonts.googleapis.com/css?family=Open+Sans:400,700&amp;subset=cyrillic

So, why not...

http://fonts.googleapis.com/css?family=Creepster&font-display=swap

The lead on the project says that caching is an issue with that (although it's been refuted by some since they already support arbitrary text params).

Adding query params reduces x-site cache hits. If we end up with something for font-display plus a bunch of params for variable fonts that could present us with problems.

They say that again later in the thread, so it sounds unlikely that we're going to get query params any time soon, but I'd love to be wrong.

Option: Download & Self-Host Them

All Google Fonts are open source, so we can snag a copy of them to use for whatever we want.

Once the font files are self-hosted and served, we're essentially writing @font-face blocks to link them up ourselves and we're free to include whatever font-display we want.

Option: Fetch & Alter

Robin Richtsfeld posted an idea to run an Ajax call from JavaScript for the font, then alter the response to include font-display and inject it.

const loadFont = (url) => { // the 'fetch' equivalent has caching issues var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.onreadystatechange = () => { if (xhr.readyState == 4 && xhr.status == 200) { let css = xhr.responseText; css = css.replace(/}/g, 'font-display: swap; }'); const head = document.getElementsByTagName('head')[0]; const style = document.createElement('style'); style.appendChild(document.createTextNode(css)); head.appendChild(style); } }; xhr.send(); } loadFont('https://fonts.googleapis.com/css?family=Rammetto+One');

Clever! Although, I'm not entirely sure how this fits into the world of font loading. Since we're now handling loading this font in JavaScript, the loading performance is tied to when and how we're loading the script that runs this. If we're going to do that, maybe we ought to look into using the official webfontloader?

Option: Service Workers

Similar to above, we can fetch the font and alter it, but do it at the Service Worker level so we can cache it (perhaps more efficiently). Adam Lane wrote this:

self.addEventListener("fetch", event => { event.respondWith(handleRequest(event)) }); async function handleRequest(event) { const response = await fetch(event.request); if (event.request.url.indexOf("https://fonts.googleapis.com/css") === 0 && response.status < 400) { // Assuming you have a specific cache name setup const cache = await caches.open("google-fonts-stylesheets"); const cacheResponse = await cache.match(event.request); if (cacheResponse) { return cacheResponse; } const css = await response.text(); const patched = css.replace(/}/g, "font-display: swap; }"); const newResponse = new Response(patched, {headers: response.headers}); cache.put(event.request, newResponse.clone()); return newResponse; } return response; }

Even Google agrees that using Service Workers to help Google Fonts is a good idea. Workbox, their library for abstracting service worker management, uses Google Fonts as the first demo on the homepage:

// Cache the Google Fonts stylesheets with a stale while revalidate strategy. workbox.routing.registerRoute( /^https:\/\/fonts\.googleapis\.com/, workbox.strategies.staleWhileRevalidate({ cacheName: 'google-fonts-stylesheets', }), ); // Cache the Google Fonts webfont files with a cache first strategy for 1 year. workbox.routing.registerRoute( /^https:\/\/fonts\.gstatic\.com/, workbox.strategies.cacheFirst({ cacheName: 'google-fonts-webfonts', plugins: [ new workbox.cacheableResponse.Plugin({ statuses: [0, 200], }), new workbox.expiration.Plugin({ maxAgeSeconds: 60 * 60 * 24 * 365, }), ], }), ); Option: Cloudflare Workers

Pier-Luc Gendreau looked into using Cloudflare workers to handle this, but then followed up with Supercharge Google Fonts with Cloudflare and Service Workers, apparently for even better perf.

It has a repo.

Option: Wait for @font-feature-values

One of the reasons Google might be dragging its heels on this (they've said the same), is that there is a new CSS @rule called @font-feature-values that is designed just for this situation. Here's the spec:

This mechanism can be used to set a default display policy for an entire font-family, and enables developers to set a display policy for @font-face rules that are not directly under their control. For example, when a font is served by a third-party font foundry, the developer does not control the @font-face rules but is still able to set a default font-display policy for the provided font-family. The ability to set a default policy for an entire font-family is also useful to avoid the ransom note effect (i.e. mismatched font faces) because the display policy is then applied to the entire font family.

There doesn't seem to be much movement at all on this (just a little), but it doesn't seem pretty awesome to wait on it.

The post Google Fonts and font-display appeared first on CSS-Tricks.

Ease-y Breezy: A Primer on Easing Functions

Css Tricks - Tue, 12/18/2018 - 9:28am

During the past few months, I’ve been actively teaching myself how to draw and animate SVG shapes. I’ve been using CSS transitions, as well as tools like D3.js, react-motion and GSAP, to create my animations.

One thing about animations in general and the documentation these and other animation tools recommend is using easing functions. I’ve been working with them in some capacity over the years, but to be honest, I would never know which function to choose for which kind of animation. Moreover, I did not know about the magic that goes into each of these functions, the notable differences between them, and how to use them effectively. But I was fine with that because I knew that easing functions somehow “smoothed” things out and mostly made my work look realistic.

Here, I present to you what I learned about easing functions in the form of a primer that I hope gives you a good understanding as you dig into animations.

How I got into easing functions

I tried to re-create a pattern called rotating snakes, an optical illusion that tricks the brains into thinking that circles rotate and “dance” when they are not.

I quickly found a gap in my knowledge when trying to build this out. It’s hard! But in the process, I discovered that easing functions play a big role in it.

I turned to JavaScript to draw a bunch of concentric circles in SVG using a library:

for (i = 1; i <= 10; i++) { drawCircle({radius: i * 10}); }

This was the result:

But that clearly does not look anything like the picture.

As I thought things through, I realized that I was looking for a certain property. I wanted the change in radius of the concentric circles to be small at the beginning and then become larger as the radius increases.

This means that the linear increase in radius using i++ won’t do the trick. We need a better formula to derive the radius. So, my next attempt looked something like this:

let i = 1; let radiusList = []; let radius = 0; while (i <= 10) { drawCircle({radius: i * 10}); if(i < 4) { i = i + 0.5 } else { i = i + 1 } }

...which got me this:

Hmm, still not what I wanted. In fact, this deviates even further from the pattern. Plus, this code is hardly customizable unwieldy to maintain.

So, I turned to math for one last attempt.

What we need is a function that changes the radius organically and exponentially. I had an “Aha!” moment and maybe you already see it, too. Easing functions will do this!

The radius of each circle should increase slowly at first, then quickly as the circles go outward. With easing, we can make move things along a curve that can slow and speed up at certain points.

A quick Google search landed me at this gist which is a well-documents list of easing functions and really saved my day. Each function takes one input value, runs formulae. and provides an output value. The input value has to be between 0 and 1. (We will dig into this reasoning later.)

A quadratic easing function looked promising because all it does is square the value it receives:

function (t) { return t*t }

Here’s the code I wound up using:

const easing = (t) => { return t*t } for(i = 0; i<=1; i=i+0.05) { const r = easing(i) * 40; drawCircle(r); }

And we have a winner!

The difference between this pattern and my first two attempts was night and day. Yay for easing functions!

This little experience got me really interested in what else easing functions could do. I scoured the internet for cool information. I found old articles, mostly related to Flash and ActionScript which had demos showing different line graphs.

That’s all pretty outdated, so here’s my little primer on easing functions.

What are easing functions?

They’re a type of function that takes a numeric input between 0 and 1. That number runs through the specified function and returns another number between 0 and 1. A value between 0-1 multiplied by another value between 0-1 always results in a value between 0-1. This special property helps us make any computation we want while remaining within specific bounds.

The purpose of an easing function is to get non-linear values from linear value inputs.

This is the crux of what we need to know about easing functions. The explanations and demos here on out are all geared towards driving home this concept.

Easing functions are a manifestation of the interpolation concept in mathematics. Interpolation is the process of finding the set of points that lie on a curve. Easing functions are essentially drawing a curve from point 0 to point 1 by interpolating (computing) different sets of points along the way.

Robert Penner was the first to define easing functions and create formulae for different ones in his book.

The five types of easing functions

There are five types of easing functions. They can be mixed, inverted and even mashed together to form additional, more complex functions. Let’s dig into each one.

Linear easing functions

This is the most basic form of easing. If the interval between the points we interpolate between 0 and 1 are constant, then we then form a linear easing function.

Going back to the concentric circles example earlier, increasing the radius of the initial circle by a constant amount (10px in that example) makes a linear function.

It should come as no surprise that linear is the default easing function. They’re extremely simple because there is no curve to the animation and the object moves in a straight, consistent direction. That said, linear functions have their drawbacks. For example, linear animations tend to feel unnatural or even robotic because real-life objects rarely move with such perfect, straight motion.

Quadratic easing functions

A quadratic easing function is created by multiplying a value between 0 and 1 by itself (e.g. 0.5*0.5). As we learned earlier, we see that this results in a value that is also between 0 and 1 (e.g. 0.5*0.5 = 0.25).

To demonstrate, let’s make 10 values between 0 and 1 with a quadratic function.

const quad_easing = (t) => t*t; let easing_vals = []; for(let i = 0; i < 1; i +=0.1) { easing_vals.push(quad_easing(i)); }

Here’s a table of all the values we get:

Input Value (x-axis) Quadratic Eased Value (y-axis) 0 0 0.1 0.01 0.2 0.04 0.3 0.09 0.4 0.16 0.5 0.25 0.6 0.36 0.7 0.49 0.8 0.64 0.9 0.81 1 1

If we were to plot this value on a graph with x-axis as the original value and y-axis as the eased value, we would get something like this:

Notice something? The curve is practically the same as the ease-in functions we commonly find, even in CSS!

Cubic, Quartic and Quintic easing functions

The final three types of easing functions behave the same, but work with a different value.

A cubic easing function is creating by multiplying a value between 0 and 1 by itself three times. In other words, it’s some value (e.g. t), cubed (e.g. t3).

Quartic functions do the same, but to the power of 4. So, if t is our value, we’re looking at t4

And, as you have already guessed, a quintic function runs to the power of 5.

The following demo will give you a way to play around with the five types of functions for a good visual of how they differ from one another.

See the Pen Plotting Easing functions by Pavithra Kodmad (@pkodmad) on CodePen.

Easing in and easing out…or both!

“An ease-in-out is a delicious half-and-half combination, like a vanilla-chocolate swirl ice cream cone.”
— Robert Penner

Ease in and ease out might be the most familiar easing animations. They often smooth out a typical linear line by slowing down at the start or end (or both!) of an animation.

Ease-in and ease-out animations can be created using any of the non-linear functions we’ve already looked at, though cubic functions are most commonly used. In fact, the CSS animation property comes with ease-in and ease-out values right out of the box, via the animation-timing-function sub-property.

  • ease-in: This function starts slow but ends faster.
  • ease-out: This function starts fast and ends slower.
  • ease-in-out: This function acts as a combination of the others, starting fast, slowing down in the middle, then ending faster.

See the Pen Easing demo by Pavithra Kodmad (@pkodmad) on CodePen.

Go ahead and play around with them on this cubic-bezier.com.

These curves can be created in JavaScript as well. I personally like and use the bezier-easing library for it. Easing.js is another good one, as is D3’s library (with a nice example from Mike Bostock). And, if jQuery is more your thing, check out this plugin or even this one.

See, it’s pretty “ease”-y!

I hope this little primer helps illustrate easing functions and interpolation in general. There are so many ways these functions can make animations more natural and life-like. Have a look at Easing.css for a UI that allows you to create custom curves and comes with a slew of preset options.

I hope the next time you use an easing function, it won’t be a blackbox to you. You now have a baseline understanding to put easing functions to use and open up a ton of possibilities when working with animations.

More on easing

We’ve only scratched the surface of easing functions here, but there are other good resources right here on CSS-Tricks worth checking out to level up even further.

The post Ease-y Breezy: A Primer on Easing Functions appeared first on CSS-Tricks.

How to Worry About npm Package Weight

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

It's all too easy to go crazy with the imports and end up with megabytes upon megabytes of JavaScript. It can be a problem as that weight burdens each and every visitor from our site, very possibly delaying or stopping them from doing what they came to do on the site. Bad for them, worse for you.

There is all sorts of ways to keep an eye on it.

You could have a peak on Bundlephobia

Bundlephobia will give you a look at the total size — both zipped and unzipped — along with download times, the number of required sub-dependencies it has, and whether or not it can be tree-shaked (tree-shook? tree-shaken?).

Speaking of "phobia," there is also Package Phobia that shows the publish and install sizes of individual packages:

You could let VS Code tell you right in the editor

Your import and require statements can lett you know the size of that particular inclusion with the Import Cost extension.

You could look at a data visualization

The Webpack Bundle Analyzer does that.

You could check out the sizes with text output

Cost of modules is another analyzer, but it seems like it only looks at package.json rather than the final bundle, then outputs it as a table:

Webpack Bundle Size Analyzer will show you a nested list of dependency weights, including the size of the bundle code itself, which is interesting:

package size will show you the weight of a comma-separated list of packages

package size has a simple CLI syntax for that:

You have another favorite way to keep your project in check?

The post How to Worry About npm Package Weight appeared first on CSS-Tricks.

Nobody is quite wrong.

Css Tricks - Mon, 12/17/2018 - 11:57am

There are two opposing views on using non-polyfillable new web features that I find are both equally common in our industry:

  1. Websites don't need to look the same in every browser. The concept of progressive enhancement helps with that. There are tools, even native language features, that help with this.
  2. If browser support isn't where I want it to be, it's just exotic eye candy for demos and not to be used.

I'm not sure I'd say either one of these is more or less correct than the other.

I also imagine it doesn't come as much of surprise that I support the thinking behind #1. It's perfectly possible to design and implement things that behave differently in different browsers and conditions. That's essentially what responsive design is, and that's pretty much the entire internet now.

The backbone of progressive enhancement is starting with a working foundation that works everywhere and layering design and functionality on top of that, when possible. There are even native language features to support the idea. @supports rules allow us to write CSS that can do something if a feature is supported and do something else if it isn't.

This is the entire use case for Modernizr and it has 22,804 stars.

I don't want to argue against progressive enhancement. Remember, I just said I support that thinking. But I do have some empathy for people and teams that choose not to go there, and end up developing more of a #2 attitude.

It is a bit more work to develop and design features that work in different ways. It might be work that is absolutely worth doing. Or it might not. Either way, it does complicate things. It's more code, it requires more attention and testing, and it's a bit harder to reason. It's technical debt.

Let me be preemptively defensive again: technical debt can be fine, and even intentional. We all incur it in everything we build. My point is that it is helpful to be smart about it and take on an amount of technical debt that is feasible for you to look after in perpetuity.

You might argue that building on a progressive enhancement foundation is, in a sense, less technical debt because you're building on such a sturdy foundation that less testing and constant tending to is required. Perhaps!

I do get behaving like a #2. It feels safer. It feels like you're being cautious and responsible. "Hey that's neat," you think. "I'll revisit it in a few years to see if I can use it for real." I might argue that 1) that's no fun and 2) almost counter-intuitively, it means you aren't willing to take a progressive enhancement approach which may make your code ultimately more frail.

It depends, I suppose. It depends on what exactly you're trying to do. It depends on the weight of that techinical debt. It depends on the team and the rate of developer churn. It depends on documentation. It depends on testing and QA.

You do you.

The post Nobody is quite wrong. appeared first on CSS-Tricks.

A CSS Venn Diagram

Css Tricks - Mon, 12/17/2018 - 11:42am

This is pretty wild: Adrian Roselli has made a series of rather complex Venn diagrams using nothing but CSS. With a combination of the Firefox dev inspector, plus a mixture of CSS Grid and the shape-outside property, it’s possible to do this and without a ton of hacks, too.

I also think it’s super cute that Adrian has made the code snippets in this post look like the display from an old monitor, like the one Chris recently broke down.

Direct Link to ArticlePermalink

The post A CSS Venn Diagram appeared first on CSS-Tricks.

Reversing an Easing Curve

Css Tricks - Mon, 12/17/2018 - 5:12am

Let’s take a look at a carousel I worked on where items slide in and out of view with CSS animations. To get each item to slide in and out of view nicely I used a cubic-bezier for the animation-timing-function property, instead of using a standard easing keyword.

See the Pen Carousel with reversed easing curve by Michelle Barker (@michellebarker) on CodePen.

A cubic-bezier can appear confusing at first glance, but when used correctly, it can add a nice touch to the user experience.

While building this carousel, I realized I not only needed a custom animation curve, but had to use it in reverse as well to get the effect right. I figured it was worth sharing what I learned because creating a custom curve and reversing it may seem tricky, but it’s actually pretty straightforward.

First, a primer on easing

Easing is the word used to describe the acceleration and deceleration of an animation’s progress along a timeline. We can plot this as a graph, where x is time and y is the animation’s progress. The graph for a linear animation, which has no acceleration or deceleration (it moves at the same speed all the way through), is a straight line:

Non-linear easing is what gives animations a more natural, life-like feel. We can apply easing to transitions and animations in CSS. The animation-timing-function property allows us to define the easing on an animation. (The same options are available for transition-timing-function.) We have four keywords to choose from:

  • linear – as described above
  • ease-in – the animation starts off slow and accelerates as it progresses
  • ease-out – the animation starts off fast and decelerates towards the end
  • ease-in-out – the animation starts off slowly, accelerates in the middle and slows down towards the end
  • ease – the default value, a variant on ease-in-out
  • Getting to know cubic-bezier

    If none of those options suit our animation, we can create a custom easing curve using the cubic-bezier function. Here’s an example:

    .my-element { animation-name: slide; animation-duration: 3s; animation-timing-function: cubic-bezier(0.45, 0.25, 0.60, 0.95); }

    If we prefer, we can write these properties as shorthand, like this:

    .my-element { animation: slide 3s cubic-bezier(0.45, 0.25, 0.60, 0.95); }

    You’ll notice the cubic-bezier function takes four values. These are the two pairs of coordinates needed in order to plot our curve onto the graph. What do those coordinates represent? Well, if you’ve used vector illustration programs, like Illustrator, the idea of vector points and “handles” that control the size and direction of the curve might be familiar to you. This is essentially what we’re plotting with a cubic-bezier curve.

    We don’t need to know about all the maths behind cubic-bezier curves in order to create a nice animation. Luckily there are plenty of online tools, like cubic-bezier.com by Lea Verou, that allow us to visualize an easing curve and copy the values. This is what I did for the above easing curve, which looks like this:

    Here, we can see the two points we need to plot, where the cubic-bezier function is cubic-bezier(x1, y1, x2, y2).

    Applying easing in two directions

    My carousel rotates in both directions — if you click the left arrow, the current item slides out of view to the right, and the next item slides in from the left; and if you click the right arrow, the reverse happens. For the items to slide into or out of view, a class is added to each item, depending on whether the user has clicked the "next” or “previous” button. My initial assumption was that I could simply reverse the animation-direction for items sliding out in the opposite direction, like this:

    .my-element--reversed { animation: slide 3s cubic-bezier(0.45, 0.25, 0.60, 0.95) reverse; }

    There’s just one problem: reversing the animation also reversed the easing curve! So, now my animation looks great in one direction, but is completely off in the other direction. Oh no!

    In this demo, the first box shows the initial animation (an item sliding left-to-right) and the second box shows what happens when the animation-direction is reversed.

    See the Pen Reverse animation by Michelle Barker (@michellebarker) on CodePen.

    You can see the two animations don’t have the same feel at all. The first box speeds up early on and slows down gently as it progresses, while the second box starts off quite sluggish, then gains a burst of speed before abruptly slowing down. This wouldn’t feel right at all for a carousel.

    We have a choice between two options to achieve this:

    1. We could create a new keyframe animation to animate the items out, and then apply the same easing as before. That’s not too hard in this example, but what if we have a more complex animation? It would take quite a bit more work to create the same animation in reverse, and we could easily make a mistake.
    2. We could use the same keyframe animation (with the animation-direction: reverse) and invert the easing curve so we get the same easing in both directions. This isn’t too hard to do, either.

    To reverse the easing curve for our reversed animation we need to rotate the curve 180 degrees on its axis and find the new coordinates.

    We can do this with some simple maths — by switching the coordinate pairs and subtracting each value from 1.

    To visualize this, imagine that our original values are:

    x1, y1, x2, y2

    Our reversed values will be:

    (1 - x2), (1 - y2), (1 - x1), (1 - y1)

    In this demo, the third box shows what we want to happen: the item sliding in the opposite direction, but with the easing reversed to give it the same feel.

    See the Pen CSS Variables to reverse easing by Michelle Barker (@michellebarker) on CodePen.

    Let’s walk through how we can calculate the reversed easing curve.

    Calculating the new curve with CSS variables

    We can use CSS variables to calculate the new curve for us! Lets assign each value to a variable:

    :root { --x1: 0.45; --y1: 0.25; --x2: 0.6; --y2: 0.95; --originalCurve: cubic-bezier(var(--x1), var(--y1), var(--x2), var(--y2)); }

    Then we can use those variables to calculate the new values:

    :root { --reversedCurve: cubic-bezier(calc(1 - var(--x2)), calc(1 - var(--y2)), calc(1 - var(--x1)), calc(1 - var(--y1))); }

    Now, if we make any changes to the first set of variables, the reversed curve will be calculated automatically. To make this a bit easier to scan when examining and debugging our code, I like to break these new values out into their own variables:

    :root { /* Original values */ --x1: 0.45; --y1: 0.25; --x2: 0.6; --y2: 0.95; --originalCurve: cubic-bezier(var(--x1), var(--y1), var(--x2), var(--y2)); /* Reversed values */ --x1-r: calc(1 - var(--x2)); --y1-r: calc(1 - var(--y2)); --x2-r: calc(1 - var(--x1)); --y2-r: calc(1 - var(--y1)); --reversedCurve: cubic-bezier(var(--x1-r), var(--y1-r), var(--x2-r), var(--y2-r)); }

    Now all that remains is to apply the new curve to our reversed animation:

    .my-element--reversed { animation: slide 3s var(--reversedCurve) reverse; }

    To help visualize this, I’ve built a little tool to calculate the reversed values of a cubic-bezier. Enter the original coordinate values to get the reversed curve:

    See the Pen Reverse cubic-bezier by Michelle Barker (@michellebarker) on CodePen.

    The post Reversing an Easing Curve appeared first on CSS-Tricks.

Annotated Build Processes

Css Tricks - Fri, 12/14/2018 - 5:59am

When you're putting together a build process for a site, it's so dang useful to look at other people's processes. I ran across Andrew Welch's "An Annotated webpack 4 Config for Frontend Web Development" the other day and was glad he blogged it. If I was kicking off a new site where I wanted a webpack build, then I'd almost certainly reference something like this rather than start from scratch. At the same time, it made me realize how build processes all have such different needs and how unique those needs are now from even a few years ago in the hay day of Grunt and Gulp build processes.

I was looking around for an annotated Gulp reference file and came across another one of Andrew's articles — "A Gulp Workflow for Frontend Development Automation" — from just one year earlier! Here's a simplified list of what he was doing with Gulp (which he explains in more detail in the post):

  • Compile Sass
  • Run Autoprefixer
  • Create Sourcemaps
  • Minify
  • Inject critical CSS and bits of scripts
  • Run Babel
  • Uglify
  • Do style injection/reloading
  • Run accessibility audit
  • Generate icon font
  • Optimize images

Speaking of Gulp and annotated build processes, I'm working on a CSS-Tricks redesign and, for various reasons, went with a Gulp build. Against my better judgment, I wrote it from scratch, and this is how far I've gotten. It doesn't feel particularly robust or efficient, so rewrites and suggestions are welcome! And speaking of Gulp, here's a recently-published boilerplate I wish I had seen before starting.

Now, a year later, here's what the build process is being asked to do:

  • Run differently-configured web servers
  • Hot module replacement
  • Dynamic code splitting
  • Lazy loading
  • Make modern and legacy code bundles
  • Cache busting
  • Create service worker
  • Compile PostCSS
  • Optimize images / create .webp
  • Process .vue files
  • Run Tailwind and PurgeCSS

It's funny how quickly things change. We're still essentially asking for help compiling files and optimizing things, but the tools we use change, the code we write changes, the way we talk about development changes, the expectations of development changes, the best practices change... makes ya sweat. &#x1f605;

The post Annotated Build Processes appeared first on CSS-Tricks.

Making SVG icon libraries for React apps

Css Tricks - Fri, 12/14/2018 - 5:20am

Nicolas Gallagher:

At Twitter I used the approach described here to publish the company’s SVG icon library in several different formats: optimized SVGs, plain JavaScript modules, React DOM components, and React Native components.

There is no One True Way© to make an SVG icon system. The only thing that SVG icon systems have in common is that, somehow, some way, SVG is used to show that icon. I gotta find some time to write up a post that goes into all the possibilities there.

One thing different systems tend to share is some kind of build process to turn a folder full of SVG files into a more programmatically digestible format. For example, gulp-svg-sprite takes your folder of SVGs and creates a SVG sprite (chunk of <symbol>s) to use in that type of SVG icon system. Grunticon processes your folder of SVGs into a CSS file, and is capable of enhancing them into inline SVG. Gallagher's script creates React components out of them, and like he said, that's great for delivery to different targets as well as performance optimization, like code splitting.

This speaks to the versatility of SVG. It's just markup, so it's easy to work with.

Direct Link to ArticlePermalink

The post Making SVG icon libraries for React apps appeared first on CSS-Tricks.

Two Ways to Build a Site That Seem Super Different But Weirdly Aren’t That Different

Css Tricks - Fri, 12/14/2018 - 5:16am

Here are two ways to build a site (abstractly) that feel diametrically opposed to me:

  1. Build a site as an SPA (Single Page App). The page loads a skeleton HTML page that executes JavaScript as quickly as it can. The JavaScript calls an API to get data, and then the page renders content. Navigation of the site is more API calls to get the data it needs and re-rendering.
  2. Build a site as statically-generated. A build process runs in which the entire site is built out as static HTML files with all the content baked into them. JavaScript isn't required at all for the site to work.

That feels just about as different as can be. But weirdly, they kinda aren't:

  1. They are both JAMstack. They can be hosted statically as neither of them needs backend languages running on the server they are hosted on.
  2. They are both building content based on an API of data. It's more obvious in the first one, but you can think of a static site generator as hitting an API of data as it runs and builds itself. It's just that the API might be temporarily created from content files it finds on disk. Or it might be the exact same API used for the former site.

That's all.

The post Two Ways to Build a Site That Seem Super Different But Weirdly Aren’t That Different appeared first on CSS-Tricks.

JavaScript to Native (and Back!)

Css Tricks - Thu, 12/13/2018 - 1:17pm

I admit I'm quite intrigued by frameworks that allow you write apps in web frameworks because they do magic to make them into native apps for you. There are loads of players here. You've got NativeScript, Cordova, PhoneGap, Tabris, React Native, and Flutter. For deskop apps, we've got Electron.

What's interesting now is to see what's important to these frameworks by honing in on their focus. Hummingbird is Flutter for the web. (There is a fun series on Flutter over on the Bendworks blog in addition to a post we published earlier this year.) The idea being you get super high performance ,thanks to the framework, and you've theoretically built one app that runs both on the web and natively. I don't know of any real success stories I can point to, but it does seem like an awesome possibility.

Nicolas Gallagher has been a strong proponent of React Native for the web.

The post JavaScript to Native (and Back!) appeared first on CSS-Tricks.

Rendering Lists Using React Virtualized

Css Tricks - Thu, 12/13/2018 - 5:20am

Working with data in React is relatively easy because React is designed to handle data as state. The hassle begins when the amount of data you need to consume becomes massive. For example, say you have to handle a dataset which is between 500-1,000 records. This can result in massive loads and lead performance problems. Well, we’re going to look at how we can make use of virtualized lists in React to seamlessly render a long list of data in your application.

We’re going to use the React Virtualized component to get what we need. It will allow us to take large sets of data, process them on the fly, and render them with little-to-no jank.

The setup

React Virtualized already has a detailed set of instructions to get it up and running, so please check out the repo to get started.

We’re going to want data to work with, so we will set up a function which uses faker to create a large data set.

function createRecord(count) { let records = []; for (let i = 0; i < count; i++) { records.push({ username: faker.internet.userName(), email: faker.internet.email() }); } return records; }

Next, we will pass it the number of data records we want to create, like so:

const records = createRecord(1000);

Alright, now we have what we need to work on rendering a list of those records!

Creating a virtualized list

Here’s the list we want to create, sans styling. We could make use of the few presentational styles that the library includes by importing the included CSS file, but we're going to leave that out in this post.

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

Go ahead and re-run that demo. Crazy fast, right?

You might wonder what the heck React Virtualized is doing behind the scenes to make that happen. Turns out it's a bunch of crazy and cool sizing, positioning, transforms and transitions that allow the records to scroll in and out of view. The data is already there and rendered. React Virtualized creates a window frame that allows records to slide in and out of view as the user scrolls through it.

To render a virtualized list in React Virtualized, we make use of its List component, which uses a Grid component internally to render the list.

First, we start by setting up rowRenderer, which is responsible for displaying a single row and sets up an index that assigns an ID to each record.

rowRenderer = ({ index, isScrolling, key, style }) => { return ( <div key={key} style={style}> <div>{this.props.data[index].username}</div> <div>{this.props.data[index].email}</div> </div> ); };

As you can see, this returns a single div node that contains two additional divs: one for the username and another for the email. You know, a common list pattern to display users.

rowRenderer accepts several parameters. Here’s what they are and what each one does:

  • index: The numeric ID of a record.
  • isScrolling: Indicates if the scrolling is occurring in the List component.
  • isVisible: Determines if a row is visible or out of view.
  • key: The records position in the array.
  • parent: Defines whether the list is a parent or a child of another list.
  • style: A style object to position the row.

Now that we know more about the rowRenderer function, let’s make put it to use in the List component:

<List rowCount={this.props.data.length} width={width} height={height} rowHeight={rowHeight} rowRenderer={this.rowRenderer} overscanRowCount={3} />

You may have noticed a few new parameters. Here’s what they are:

  • rowCount: This takes the numbers of a row in a list that we pass to calculate the length of our list.
  • width: The width of the list.
  • height: The height of the list.
  • rowHeight: This can be a number or a function that returns a row height given its index.
  • rowRenderer: This is responsible for rendering the row. the list is not supposed to be passed directly, so we pass the rowRenderer function that we created in this tutorial.
  • overscanRowCount: This is used to render additional rows in the direction the user scrolls. It reduces the chances of the user scrolling faster than the virtualized content is rendered.

At the end, your code should look something like this;

const { List } = ReactVirtualized ... const height = 700; const rowHeight = 40; const width = 800; class App extends React.Component { rowRenderer = ({ index, isScrolling, key, style }) => { return ( <div key={key} style={style}> <div>{this.props.data[index].username}</div> <div>{this.props.data[index].email}</div> </div> ); }; render() { return ( <div> <h2>Details</h2> <List rowCount={this.props.data.length} width={width} height={height} rowHeight={rowHeight} rowRenderer={this.rowRenderer} overscanRowCount={3} /> </div> ); } } Cell measurer

According to the documentation, a cell measurer is a higher-order component that is used to temporarily render a list. It’s not yet visible to the user at this point, but the data is held and ready to display.

Why should you care about this? The popular use case is a situation where the value of your rowHeight is dynamic. React Virtualized can render the height of the row on render then cache that height so it no longer needs to calculate as data scrolls out of view — it's always the right height, no matter the content it contains!

First, we create our cache, which can be done in our component’s constructor using CellMeasurerCache:

constructor() { super() this.cache = new CellMeasurerCache({ fixedWidth: true, defaultHeight: 100 }) }

We make use of the cache when we set up the List component;

<List rowCount={this.props.data.length} width={rowWidth} height={listHeight} deferredMeasurementCache={this.cache} rowHeight={this.cache.rowHeight} rowRenderer={this.renderRow} overscanRowCount={3} />

The value passed to deferredMeasurementCache will be used to temporarily rendering the data, then — as the calculated value for rowHeight comes in — additional rows will flow in like they were always there.

Next, though, we will make use of React Virtualized’s CellMeasurer component inside our rowRenderer function instead of the div we initially set up as a placeholder:

rowRenderer = ({ index, parent, key, style }) => { return ( <CellMeasurer key={key} cache={this.cache} parent={parent} columnIndex={0} rowIndex={index} > <div style={style}> <div>{this.props.data[index].username}</div> <div>{this.props.data[index].email}</div> </div> </CellMeasurer> ); };

Now the data is fetched, cached and ready to display in the virtual window at will!

Virtualized table

Yeah, so the main point of this post is to cover lists, but what if we actually want to render data to a table instead? React Virtualized has you covered on that front, too. In this case, we will make use of Table and Column components that come baked into React Virtualized.

Here’s how we would put those components to use in our primary App component:

class App extends React.Component { render() { return ( <div> <h2>Details</h2> <Table width={500} height={300} headerHeight={20} rowHeight={40} rowCount={this.props.data.length} rowGetter={({ index }) => this.props.data[index]} > <Column label='Username' dataKey='username' width={100} /> <Column width={200} label='Email' dataKey='email' /> </Table> </div> ); } }

The Table component accepts the following parameters:

  • width: The width of the table.
  • height: The height of the table.
  • headerHeight: The table header height.
  • rowHeight: The height of a row given its index.
  • rowCount: This is the initial number of rows we want in the table. It’s the same as the way we defined the number of records we wanted to start with in the List component example.
  • rowGetter: This returns the data of a specific row by its index.

If you take a look at the Column component, you will notice that we put a dataKey parameter to use. That passes the data for each column we called in the dataKey, which receives a unique identifier for that data. Remember that in the function where we create our random data, we make use of two keys; username and email. This is why we have the dataKey of one column set as username and the other set as email.

In conclusion

Hopefully, this walkthrough gives you a good idea of what React Virtualized is capable of doing, how it can make rendering large data sets into lists and tables super fast, and how to put it to use in a project.

We've only scratched the surface here. The library is capable of handling a lot of other use cases, like generating placeholders for the data records on scroll, an infinite loading component to fetch and cache data in real-time, a method for allowing arrow keys to navigate through the data, and a slick grid and masonry layouts that we didn't even cover here.

That should give you a lot to play around with!

Plus, the package is highly maintained. In fact, you can join the Slack group to keep up with the project, contribute to it, and generally get to connect with other folks.

It’s also worth noting that React Virtualized has it own tag in StackOverflow and that can be a good resource to find questions other people have asked about it, or even post your own questions.

Oh, and if you’ve put React Virtualized to use on a project, we’d love to know it! Share it with us in the comments with some notes on how you approached it or what you learned from it.

The post Rendering Lists Using React Virtualized appeared first on CSS-Tricks.

Level up your JavaScript error monitoring

Css Tricks - Thu, 12/13/2018 - 5:16am

(This is a sponsored post.)

Automatically detect and diagnose JavaScript errors impacting your users with Bugsnag. Get comprehensive diagnostic reports, know immediately which errors are worth fixing, and debug in a fraction of the time.

Bugsnag detects every single error and prioritizes errors with the greatest impact on your users. Get support for 50+ platforms and integrate with the development and productivity tools your team already uses.

Bugsnag is used by the world's top engineering teams including Airbnb, Slack, Pinterest, Lyft, Square, Yelp, Shopify, Docker, and Cisco. Start your free trial today.

Direct Link to ArticlePermalink

The post Level up your JavaScript error monitoring appeared first on CSS-Tricks.

Keep Math in the CSS

Css Tricks - Wed, 12/12/2018 - 7:22am

There is a sentiment that leaving math calculations in your CSS is a good idea that I agree with. This is for math that you could calculate at authoring time, but specifically chose not to. For instance, if you needed a 7-column float-based grid (don't ask), it's cleaner and more intuitive:

.col { /* groan */ width: 14.2857142857%; /* oh, I get it */ width: calc(100% / 7); }

You could probably prove that the calc() takes the computer 0.0000001% longer, so explicitly defining the width is technically faster for performance reason — but that is about the equivalent of not using punctuation in sentences because it saves HTML weight.

That math can be a little more complicated as you continue. For example, like in our use cases for calc() article, what about columns in that 7-column grid that span?

.column-1-7 { width: calc(100% / 7); } .column-2-7 { width: calc(100% / 7 * 2); } .column-3-7 { width: calc(100% / 7 * 3); }

I'd say that's rather clean to read and manage.

The readability of the math can be enhanced by comments if it gets too complicated. Say you are trying to account for a margin-based gutter with padding inside of an element:

.parent { width: 600px; padding: 18px; } .left { /* base width - 1/2 horizontal padding */ width: calc(400px - 18px); margin-right: 1rem; /* gutter */ } .right { /* base width - 1/2 horizontal padding - gutter */ width: calc(200px - 1rem - 18px); }

Again, I'd say that's pretty readable, but it's also a good amount of repetition. This might call for using variables. We'll do it with CSS custom properties for fun. You have to pick what is worthy of a variable and what isn't. You might need fewer comments as the code becomes somewhat self-documenting:

.parent { --padding: 18px; --gutter: 1rem; width: 600px; padding: var(--padding); } .left { width: calc(400px - var(--padding)); margin-right: var(--gutter); } .right { width: calc(200px - var(--gutter) - var(--padding)); }

That is a decent balance to me. Here's a step further:

.parent { --padding: 18px; --gutter: 1rem; --parentWidth: 600px; --leftSize: 2/3; --rightSize: 1/3; width: var(--parentWidth); padding: var(--padding); } .left { width: calc(calc(var(--parentWidth) * var(--leftSize)) - var(--padding)); margin-right: var(--gutter); } .right { width: calc(calc(var(--parentWidth) * var(--rightSize)) - var(--gutter) - var(--padding)); }

Every single number has been given a variable in there. Too far? Maybe. It certainly makes those width declarations pretty hard to wrap your head around quickly. Ana Tudor does some serious stuff with calc(), as proof that everyone's comfort level with this stuff is different.

One of the things that made me think of all this is a recent article from James Nash — "Hardcore CSS calc()" — where he builds this:

While the solution took a heavily math-y road to get there, it ends up being only sort of medium-level calculation on the ol' complexity meter. And note that not everything gets a variable' only the most re-used bits:

See the Pen Fluid 1 + 2 thumbnail block by James Nash (@cirrus) on CodePen.

The post Keep Math in the CSS appeared first on CSS-Tricks.

Web Designs That Feel Like Ancient History, but Are More Recent Than You Think

Css Tricks - Wed, 12/12/2018 - 5:03am

Flickr announced not long ago that they are limiting free accounts to 1,000 photos. I don't particularly mind that (because it seems like sound business sense), although it is a bit sad that a ton of photos will be nuked from the internet. I imagine the Internet Archive will swoop in and get most of it. And oh hey, the Twitter account @FlickrJubilee is showcasing Flickr users that could really use a gifted pro account so their amazing photos are not lost, if you're feeling generous and want to contribute.

This change doesn't affect pro accounts. I've been pro forever on Flickr, so my photos were never at risk, but the big change has me thinking it's about time to spin down Flickr for myself. I've been keeping all my photos on iCloud/Photos for years now anyway so it seems kind redundant to keep Flickr around.

I went into the Flickr settings and exported all my photos, got a bunch of gigabytes of exported photos, and loaded them into Photos. Sadly, the exported photos have zero metadata, so there will forever be this obnoxious chunk of thousands upon thousands of photos in my Photos collection that all look like they were taken on the same day and with no location.

Anyway, that was way too long of an intro to say: I found a bunch of old website screenshots! Not a ton, but it looks like I used Flickr to store a handful of web designs I found interesting in some way a number of years back. What's interesting today is how dated they look when they were created not that long ago. Shows how fast things change.

Here they are.

It's not terribly surprising to me to hear people push back on the same-ness of web design these days, and to blame things like frameworks, component-driven architecture, and design systems for it. It wasn't long ago when it seemed like we were trying harder to be fancy and unique with our designs — things like shadow treatments, reflective images and skeuomorphic enhancements. I don't mean to make sweeping generalizations here... merely a difference between what we considered to be boring and fancy work back than compared to now, of course.

The post Web Designs That Feel Like Ancient History, but Are More Recent Than You Think appeared first on CSS-Tricks.

Prototypes and production

Css Tricks - Tue, 12/11/2018 - 11:19am

There’s an interesting distinction that Jeremy Keith defines between prototype code and production code in this post and I’ve been thinking about it all week:

...every so often, we use the materials of front-end development—HTML, CSS, and JavaScript—to produce something that isn’t intended for production. I’m talking about prototyping.

What’s interesting is that—when it comes to prototyping—our usual front-end priorities can and should go out the window. The priority now is speed. If that means sacrificing semantics or performance, then so be it. If I’m building a prototype and I find myself thinking “now, what’s the right class name for this component?”, then I know I’m in the wrong mindset. That question might be valid for production code, but it’s a waste of time for prototypes.

I love the way that Jeremy phrases all of this and how he describes that these two environments require entirely separate mindsets. When prototyping, for instance, we can probably overlook optimizing for accessibility or performance and even let our CSS standards slip in order to get something in the browser and test it as quickly as possible.

Earlier this year, I echoed some of the same thoughts when I wrote a little bit about prototyping in the browser:

I reckon that the first time a designer and/or front-end developer writes code, it should never be in a production environment. Having the leeway and freedom to go crazy with the code in a safe environment focuses your attention on the design and making it compatible with a browser’s constraints. After this, you can think about grooming the code from a hot, steaming heap of garbage into lovely, squeaky-clean, production-ready poetry. Translating the static mockups into an interactive prototype is the first step, but it’s vital to have a next step to enforce your code standards.

Direct Link to ArticlePermalink

The post Prototypes and production appeared first on CSS-Tricks.

Chromedge and headcount

QuirksBlog - Tue, 12/11/2018 - 6:16am

So Microsoft is going to retire EdgeHTML and use Chromium instead for Edge while not really answering the question if the web [is] better off with less engine diversity. This upset people, and Mozilla, especially, is worrying about the future:

Will Microsoft’s decision make it harder for Firefox to prosper? It could. Making Google more powerful is risky on many fronts. [...] If one product like Chromium has enough market share, then it becomes easier for web developers and businesses to decide not to worry if their services and sites work with anything other than Chromium. That’s what happened when Microsoft had a monopoly on browsers in the early 2000s before Firefox was released. And it could happen again.

Before you lament the return to a Microsoft-like monopoly, remember what happened to Microsoft’s monopoly. In fact, remember what happened to the lineal descendant of that monopoly just last week. Near-monopolies do not necessarily mean the end of the web.

Browser diversity

Back then, Microsoft stopped developing IE because it thought it had won. Right now, Google is doing no such thing — in fact, I think it’s moving too fast rather than too slow.

Back then, Microsoft welcomed the IE-only badges that sprung up on countless websites. Right now, the Chrome devrel team does not. In fact, they don’t hesitate to criticise Chrome-only sites created by other parts of Google.

Also, don’t forget WebKit. Right now web developers pretend there are only two rendering engines left, Gecko and Blink, but there is in fact a third one, and especially on mobile it’s quite important. (When did you last create a site that didn’t really have to work on iOS?)

Today’s situation is very different from fifteen years ago — though I still think web developers switching to Firefox as their default browser is a good idea. (No, I haven’t yet done so either.)

Headcount

But I don’t really want to talk about browser diversity, or about the relative merits of present-day Google and past Microsoft.

Instead, I want to talk about headcount.

The IE team first asked for my regarded opinion somewhere in 2005 or so, when they were gearing up toward IE7. Since then I’ve been in touch with them, and followed their progress with interest, occasionally submitting feature lists or clarifying our web developer point of view.

During all those years, I had the distinct feeling the IE team was under-staffed — a feeling that was occasionally, if privately, confirmed by team members. It seemed that, while Microsoft had decided to continue the development of IE, it didn’t want to commit the full resources that the project warranted.

That’s why, in the immediate aftermath of Microsoft confirming the rumour, I was quite surprised to see a We’re hiring message. (Granted, the actual job descriptions don’t mention Chromium, but they were written in October or November.)

Next, I saw this tweet by Tom Dale:

I understand why people are nervous about a Chrome monoculture. I think this case is a little different though. Microsoft has an army of engineers working on Edge. They’re one of the few companies who can go toe-to-toe with Google funding browser development.

Now I don’t follow Tom, and the only reason I saw his tweet is that it was retweeted by an Edge team member. Sure, RT !== endorsement, but this was a curious coincidence, to say the least.

Is one unexpected benefit of the switch to Chromium that the Edge team can actually expand? It’s easier to get Chromium engineers than EdgeHTML ones, that’s for sure.

Android

If Microsoft does solve its headcount problems, then things get interesting — especially on Android. Sure, Microsoft has more opportunities for expanding its market share elsewhere, notably Windows 7 (where EdgeHTML never ran), but Android is by far the most interesting one.

One huge advantage of moving to Chromium is that Edge can now be easily ported to Android. This tweet appears to confirm that an Android version is in the planning.

Let’s jump sideways for a moment. Google Services is a suite of Android apps such as Play, Search, Maps, YouTube, and other crucial services that pretty much define how useful a smartphone is. It also contains Google Chrome. Android vendors get the option of using Google Services for free, provided they use ALL of them. All non-Chinese ones actually do so, and Google Services is an important part of the hold Google has on the web and mobile markets. Also, it puts Google Chrome on every Android phone.

What if Microsoft offered the Android vendors an alternative? Microsoft has a search engine, maps, and other services. YouTube can be viewed in a browser as well as in an app — and now it has the browser. Only an alternative to the Play Store is missing — so far. It’s quite possible that some Android vendors would seriously consider such an offer. It would ease Google’s stranglehold.

In that light, I found it interesting that HTC is experimenting with Brave as its default browser on one phone model. (True, the HTC Exodus is a “blockchain phone” and when I recently visited the local phone store they didn’t have any HTC whatsoever on offer, and nomen is most definitely not an omen. Still, interesting.) And if this example doesn’t convince you, remember Samsung Internet. Non-Google Chromium browsers are a thing on Android. But they aren't part of a set of services — yet.

Anyway, IF the Edge team gets more people, and IF Microsoft decides to go the Android route, the switch to Chromium may become interesting very fast.

Syndicate content
©2003 - Present Akamai Design & Development.