Developer News

Keyboard-Only Focus Styles

Css Tricks - Wed, 11/14/2018 - 5:01am

Like Eric Bailey says, if it's interactive, it needs a focus style. Perhaps your best bet? Don't remove the dang outlines that focusable elements have by default. If you're going to rock a button { outline: 0; }, for example, then you'd better do a button:focus { /* something else very obvious visually */ }. I handled a ticket just today where a missing focus style was harming a user who relies on visual focus styles to navigate the web.

But those focus styles are most useful when tabbing or otherwise navigating with a keyboard, and less so when they are triggered by a mouse click. Now we've got :focus-visible! Nelo writes:

TLDR; :focus-visible is the keyboard-only version of :focus.

Also, the W3C proposal mentions that :focus-visible should be preferred over :focus except on elements that expect a keyboard input (e.g. text field, contenteditable).

(Also see his article for a good demo on why mouse clicking and focus styles can be at odds, beyond a general dislike of fuzzy blue outlines.)

Browser support for :focus-visible is pretty rough:

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

DesktopChromeOperaFirefoxIEEdgeSafariNoNo4*NoNoNoMobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid FirefoxNoNoNoNoNo62*

But it does have Firefox support, and as Lea Verou says:

... once Chrome ships its implementation it will explode in a matter of 1-2 months.

That's generally how things go these days. Once two major browsers have support — and one of them is Chrome — that's a huge enough slice of the web that can start using it. Especially when it can be done as safely as this property.

Safely, as in, there is an official polyfill, meaning you can nuke default focus styles and just use :focus-visible styles:

/* Remove outline for non-keyboard :focus */ *:focus:not(.focus-visible) { outline: none; } /* Optional: Customize .focus-visible */ .focus-visible { outline: lightgreen solid 2px; }

But, as Patrick H. Lauke documented, you can do it even without the polyfill, using careful selector usage and un-doing styles as needed:

button:focus { /* Some exciting button focus styles */ } button:focus:not(:focus-visible) { /* Undo all the above focused button styles if the button has focus but the browser wouldn't normally show default focus styles */ } button:focus-visible { /* Some even *more* exciting button focus styles */ }

Seems like a nice improvement for the web.

The post Keyboard-Only Focus Styles appeared first on CSS-Tricks.

Dark modes with CSS

Css Tricks - Wed, 11/14/2018 - 5:00am

With the introduction of dark mode in macOS, Safari Technology Preview 68 has released a new feature called prefers-color-scheme which lets us detect whether the user has dark mode enabled with a media query.

That’s right. If this becomes a little bit more supported in other browsers, then we might potentially soon have a way to toggle on night modes with a few lines of CSS!

Recently Mark Otto described how we can start using prefers-color-scheme today in order to create themes that dynamically adjust to the new user setting. And the neat thing about this post is that Mark sort of frames it as an accessibility issue and shows how he uses it on his own website to adjust images so that they’re not too bright for the user:

@media (prefers-color-scheme: dark) { img { opacity: .75; transition: opacity .5s ease-in-out; } img:hover { opacity: 1; } }

In the code above, Mark detects whether the user has dark mode enabled with the media query and then makes the images darker so that they match a dark background. This reminds me of an excellent post by Marcin Wichary where he explores a similar technique and goes one step further by adding all sorts of filters to make sure they have a much higher contrast.

Andy Clarke also wrote up some thoughts about how to take this fancy new CSS feature and how we might apply a dark theme across our website. He describes how to pick colors so our light/dark themes are consistent in terms of branding and how we might want to use a lighter font-weight for darker backgrounds. He writes:

Designing for dark mode shouldn’t stop with choosing darker colours. You should also consider altering typography styles to maintain readability for people who use dark mode. Light text against dark backgrounds appears higher in contrast than when the same colours are used in reverse, so to make your dark mode designs easier to read you’ll need to add more white/dark space to your text.

If your fonts offer a lighter weight, using that for your dark mode design will open up the letterforms and make them appear further apart...

What was that? It sure sounded like the joyous applause of typography nerds and designers everywhere!

The post Dark modes with CSS appeared first on CSS-Tricks.

CSS and Network Performance

Css Tricks - Tue, 11/13/2018 - 12:47pm

JavaScript and images tend to get the bulk of the blame for slow websites, but Harry explains very clearly why CSS is equally to blame and harder to deal with:

  1. A browser can’t render a page until it has built the Render Tree;
  2. the Render Tree is the combined result of the DOM and the CSSOM;
  3. the DOM is HTML plus any blocking JavaScript that needs to act upon it;
  4. the CSSOM is all CSS rules applied against the DOM;
  5. it’s easy to make JavaScript non-blocking with async and defer
    attributes;
  6. making CSS asynchronous is much more difficult;
  7. so a good rule of thumb to remember is that your page will only render as quickly as your slowest stylesheet.

There are lots of options to do better with this, including some interesting things that HTTP/2 unlocks.

Check out Šime Vidas's takeaways as well. It's all fascinating, but the progressive rendering stuff is particularly cool. I suspect many CSS-in-JS libraries could/should help with doing things this way.

Direct Link to ArticlePermalink

The post CSS and Network Performance appeared first on CSS-Tricks.

The “C” in CSS: The Cascade

Css Tricks - Tue, 11/13/2018 - 5:01am

Following up from Geoff’s intro article on The Second "S" in CSS, let’s now move the spotlight to the "C" in CSS — what we call the Cascade. It’s where things start to get messy, and even confusing at times.

Have you ever written a CSS property and the value doesn’t seem to work? Maybe you had to turn to using !important to get it going. Or perhaps you resorted to writing the CSS inline on the element in the HTML file.

<div style="background:orange; height:100px; width:100px;"> Ack, inline! </div>

Speaking of inline styles, have you wondered why SVG editors use them instead of a separate CSS file? That seems kinda weird, right?

<svg id="icon-logo-star" viewBox="0 0 362.62 388.52" width="100%" height="100%"> <style> .logo { fill: #ff9800; } </style> <title>CSS Tricks Logo</title> <path class="logo" d="M156.58 239l-88.3 64.75c-10.59 7.06-18.84 11.77-29.43 11.77-21.19 0-38.85-18.84-38.85-40 0-17.69 14.13-30.64 27.08-36.52l103.6-44.74-103.6-45.92C13 142.46 0 129.51 0 111.85 0 90.66 18.84 73 40 73c10.6 0 17.66 3.53 28.25 11.77l88.3 64.75-11.74-104.78C141.28 20 157.76 0 181.31 0s40 18.84 36.5 43.56L206 149.52l88.3-64.75C304.93 76.53 313.17 73 323.77 73a39.2 39.2 0 0 1 38.85 38.85c0 18.84-12.95 30.61-27.08 36.5l-103.61 45.91L335.54 239c14.13 5.88 27.08 18.83 27.08 37.67 0 21.19-18.84 38.85-40 38.85-9.42 0-17.66-4.71-28.26-11.77L206 239l11.77 104.78c3.53 24.72-12.95 44.74-36.5 44.74s-40-18.84-36.5-43.56z"></path> </svg>

Well, the cascade has a lot to do with this. Read on to find out how styling methods affect what's being applied to your elements and how to use the cascade to your advantage because, believe me, it’s a wonderful thing when you get the hang of it.

TL;DR: Jump right to the CSS order diagram for a visual of how everything works.

The cascade cares about how and where styles are written

There are a myriad of ways you can apply CSS rules to an element. Below is an example of how stroke: red; can be applied to the same element. The examples are ordered in ascending priority, where the highest priority is at the bottom:

<!-- Inheritance --> <g style="stroke: red"> <rect x="1" y="1" width="10" height="10" /> <!-- inherits stroke: red --> </g> <!-- Inline attributes --> <rect x="1" y="1" width="10" height="10" stroke="red" /> <!-- External style sheet --> <link rel="stylesheet" href="/path/to/stylesheet.css"> <!-- Embedded styles --> <style> rect { stroke: red; } </style> <!-- Different specificity or selectors --> rect { stroke: red; } .myClass { stroke: red; } #myID { stroke: red; } <!-- Inline style --> <g style="stroke: red"></g> <!-- Important keyword --> <g style="stroke: red !important"></g>

Inheritance? Embedded? External? Inline? Specificity? Important? Yeah, lots of terms being thrown around. Let’s break those down a bit because each one determines what the browser ends up using when a web page loads.

Elements can inherit styles from other elements

Both HTML and SVG elements can inherit CSS rules that are applied to other elements. We call this a parent-child relationship, where the element the CSS is applied to is the parent and the element contained inside the parent is the child.

<div class="parent"> <div class="child">I'm the child because the parent is wrapped around me.</div> </div>

If we set the text color of the parent and do not declare a text color on the child, then the child will look up to the parent to know what color its text should be. We call that inheritance and it’s a prime example of how a style cascades down to an element it matches... or "bubbles up" the chain to the next matched style.

However, inheritance has the lowest priority among styling methods. In other words, if a child has a rule that is specific to it, then the inherited value will be ignored, even though the inherited value may have an important keyword. The following is an example:

<div class="parent" style="color: red !important;"> <div class="child">I'm the child because the parent is wrapped around me.</div> </div>

See the Pen Child ignores inline inheritance with !important by Geoff Graham (@geoffgraham) on CodePen.

SVG inline attributes

For SVG elements, we can also apply styles using inline attributes, where those have the second lowest priority in the cascade. This means the CSS rules in a stylesheet will be able to override them.

<rect x="1" y="1" width="10" height="10" stroke="red" /> rect { stroke: blue; }

See the Pen Stylesheet overrides SVG inline attributes by Geoff Graham (@geoffgraham) on CodePen.

Most SVG editors use inline attributes for portability; that is, the ability to copy some elements and paste them elsewhere without losing the attributes. Users can then use the resultant SVG and style its elements using an external stylesheet.

Stylesheets

Stylesheets are divided into two flavors: external and embedded:

<!-- External style sheet --> <link rel="stylesheet" href="/path/to/stylesheet.css"> <!-- Embedded styles --> <style> div { border: 1px solid red } </style>

Embedded styles have the same priority as external stylesheets. Therefore, if you have the same CSS rules, ordering rules applies.

See the Pen Embedded styles override stylesheet rules by Geoff Graham (@geoffgraham) on CodePen.

All stylesheets follow ordering rules, where files that are defined later, will have higher priority than those defined earlier. In this example, stylesheet-2.css will take precedence over the stylesheet-1.css file because it is defined last.

<link rel="stylesheet" href="/path/to/stylesheet-1.css"> <link rel="stylesheet" href="/path/to/stylesheet-2.css"> Specificity or selectors

How you select your elements will also determine which rules are applied, whereby tags (e.g. <p>, <div>), classes (e.g. .my-class) and IDs (e.g. #myI-id) have ascending priorities.

See the Pen Specificity by selectors by Geoff Graham (@geoffgraham) on CodePen.

In the example above, if you have a div element with both .my-class and #my-id, the border will be red because IDs have higher priority than classes and tags.

*Specificity has higher priority than ordering rules, therefore, irrespective if your rule is at the top or bottom. Specificity still has higher priority and will be applied.

Ordering

CSS rules always prioritize from left-to-right, then from top-to-bottom.

<!-- Blue will be applied because it is on the right --> <div style="border: 1px solid red; border: 1px solid blue;"></div> <style> div { border: 1px solid red; border: 1px solid blue; /* This will be applied because it is at the bottom */ } </style> Inline styles

Inline styles have the second highest priority, just below the !important keyword. This means that inline styles are only overridden by the important keyword and nothing else. Within inline styles, normal ordering rules applies, from left-to-right and top-to-bottom.

<div style="1px solid red;"></div> The important keyword

Speaking of the !important keyword, it is used to override ordering, specificity and inline rules. In other words, it wields incredible powers.

Overriding inline rules <style> div { /* This beats inline styling */ border: 1px solid orange !important; /* These do not */ height: 200px; width: 200px; } </style> <div style="border: 1px solid red; height: 100px; width: 100px;"></div>

In the example above, without the important keyword, the div would have a red border because inline styling has higher priority than embedded styles. But, with the important keyword, the div border becomes orange, because the important keyword has higher priority than inline styling.

Using !important can be super useful, but should be used with caution. Chris has some thoughts on situations where it makes sense to use it.

Overriding specificity rules

Without the important keyword, this div border will be blue, because classes have higher priority than tags in specificity.

<style> /* Classes have higher priority than tags */ .my-class { border: 1px solid blue; height: 100px; width: 100px; } div { border: 1px solid red; height: 200px; width: 200px; } </style> <div class="my-class"></div>

See the Pen Classes beat tags by Geoff Graham (@geoffgraham) on CodePen.

But! Adding the important keyword to the tag rules tells the element to ignore the cascade and take precedence over the class rules.

<style> .my-class { border: 1px solid red; } /* The important keyword overrides specificity priority */ .my-class { border: 1px solid blue !important; } </style> <div class="my-class"></div>

See the Pen !important ignores the cascade by Geoff Graham (@geoffgraham) on CodePen.

Overriding ordering rules

OK, so we’ve already talked about how the order of rules affects specificity: bottom beats top and right beats left. The surefire way to override that is to put !important into use once again.

In this example, the div will take the red border, even though the blue border is the bottom rule. You can thank !important for that handiwork.

<style> div { border: 1px solid red !important; } /* This wins, despite the ordering */ div { border: 1px solid blue; } </style> <div></div>

See the Pen Important wins over ordering by Geoff Graham (@geoffgraham) on CodePen.

Visualizing the cascade

Who knew there was so much meaning in the "C" of CSS? We covered a ton of ground here and hopefully it helps clarify the way styles are affected and applied by how we write them. The cascade is a powerful feature. There are opinions galore about how to use it properly, but you can see the various ways properties are passed and inherited by elements.

More of a visual learner? Here’s a chart that pulls it all together.

Download chart

The post The “C” in CSS: The Cascade appeared first on CSS-Tricks.

A Bunch of Options for Looping Over querySelectorAll NodeLists

Css Tricks - Mon, 11/12/2018 - 4:54am

A common need when writing vanilla JavaScript is to find a selection of elements in the DOM and loop over them. For example, finding instances of a button and attaching a click handler to them.

const buttons = document.querySelectorAll(".js-do-thing"); // There could be any number of these! // I need to loop over them and attach a click handler.

There are SO MANY ways to go about it. Let's go through them.

forEach

forEach is normally for arrays, and interestingly, what comes back from querySelectorAll is not an array but a NodeList. Fortunately, most modern browsers support using forEach on NodeLists anyway.

buttons.forEach((button) => { button.addEventListener('click', () => { console.log("forEach worked"); }); });

If you're worried that forEach might not work on your NodeList, you could spread it into an array first:

[...buttons].forEach((button) => { button.addEventListener('click', () => { console.log("spread forEach worked"); }); });

But I'm not actually sure if that helps anything since it seems a bit unlikely there are browsers that support spreads but not forEach on NodeLists. Maybe it gets weird when transpiling gets involved, though I dunno. Either way, spreading is nice in case you want to use anything else array-specific, like .map(), .filter(), or .reduce().

A slightly older method is to jack into the array's natural forEach with this little hack:

[].forEach.call(buttons, (button) => { button.addEventListener('click', () => { console.log("array forEach worked"); }); });

Todd Motto once called out this method pretty hard though, so be advised. He recommended building your own method (updated for ES6):

const forEach = (array, callback, scope) => { for (var i = 0; i < array.length; i++) { callback.call(scope, i, array[i]); } };

...which we would use like this:

forEach(buttons, (index, button) => { console.log("our own function worked"); }); for .. of

Browser support for for .. of loops looks pretty good and this seems like a super clean syntax to me:

for (const button of buttons) { button.addEventListener('click', () => { console.log("for .. of worked"); }); } Make an array right away const buttons = Array.prototype.slice.apply( document.querySelectorAll(".js-do-thing") );

Now you can use all the normal array functions.

buttons.forEach((button) => { console.log("apply worked"); }); Old for loop

If you need maximum possible browser support, there is no shame in an ancient classic for loop:

for (let i = 0; i < buttons.length; ++i) { buttons[i].addEventListener('click', () => { console.log("for loop worked"); }); } Libraries

If you're using jQuery, you don't even have to bother....

$(".buttons").on("click", () => { console.log("jQuery works"); });

If you're using a React/JSX setup, you don't need think about this kind of binding at all.

Lodash has a _.forEach as well, which presumably helps with older browsers.

_.forEach(buttons, (button, key) => { console.log("lodash worked"); }); Poll

Twitter peeps:

const els = document.querySelectorAll(".foo");

// which loop do you use? one of these? other?

— Chris Coyier (@chriscoyier) November 7, 2018

Also here's a Pen with all these options in it.

The post A Bunch of Options for Looping Over querySelectorAll NodeLists appeared first on CSS-Tricks.

Why Browsers Download Stylesheets with Non-Matching Media Queries

Css Tricks - Mon, 11/12/2018 - 4:53am

Say you have a stylesheet linked up like this:

<link href="mobile.css" rel="stylesheet" media="screen and (max-width: 600px)">

But as the page loads, you're on a desktop browser where the screen is 1753px wide. The browser should just skip loading that stylesheet entirely, right? It doesn't. Thomas Steiner explains:

it turns out that the CSS spec writers and browser implementors are actually pretty darn smart about this:

The thing is, the user could always decide to resize their window (impacting width, height, aspect ratio), to print the document, etc., and even things that at first sight seem static (like the resolution) can change when a user with a multi-screen setup moves a window from say a Retina laptop screen to a bigger desktop monitor, or the user can unplug their mouse, and so on.

What browsers do do (heh, &#x1f4a9;) is apply a Lowest download priority.

Direct Link to ArticlePermalink

The post Why Browsers Download Stylesheets with Non-Matching Media Queries appeared first on CSS-Tricks.

The ironic inaccessibility of a11y

Css Tricks - Sun, 11/11/2018 - 6:54pm

This resonated with me:

It’s ironic to me that the numeronym “a11y” lacks accessibility: it’s not immediately decipherable by humans who aren’t “in the club”; and, in some fonts, it’s visually indistinguishable from the word “ally” (with lowercase L’s), which can foil searches for clarity.

— Eric Meyer (@meyerweb) November 5, 2018

Because I bet it took me a year after seeing that acronym ("numeronym", I guess) for the first time to know that was just a stand-in for the word "accessibility". I'm only now just understanding that "i18n" means "Internationalization" and "l10n" means "Localization". I wonder how many conversations or articles I've missed because I just assumed the weird moniker was referring to something that had nothing to do with me. On the flip side, I wonder what good has come from having these cool words form a banner to rally under.

Lots of good conversation in that thread. I don't know enough to have an opinion about whether anyone else should or shouldn't use it, but remembering my own confusion, I think I'll avoid it around here.

The post The ironic inaccessibility of a11y appeared first on CSS-Tricks.

When’s the last time you SFTP’d (or the like) into a server and changed a file directly?

Css Tricks - Fri, 11/09/2018 - 5:06am

In the grand tradition of every single poll question I've ever posted, the poll below has a has a fundamental flaw. In this case, there is no option between "In the last month" and "Never" but, alas, the results are interesting:

When's the last time you SFTP'd (or the equiv) into a server and changed a file directly?

— Chris Coyier (@chriscoyier) October 9, 2018

What I was trying to get at with this poll is how many people do and don't do any sort of editing of production files directly and instead work locally. I don't think I need to launch a major investigation to know that it's most people and more than in the past.

Most workflows these days have us working locally and pushing new and updated files through a version control system, and even through systems beyond that, perhaps continuous integration processes, testing processes, actions, deployment — it's big world of DevOps out there! Rarely do we skip the line and dip our fingers into production servers and make live manipulations. Cowboy coding, they sometimes call it.

But just because you don't generally code that way doesn't mean you never do it, which is another flaw of this poll. I know DevOps nerds who are constantly SSH-ing into servers to manipulate configuration files. I personally still hop into Coda and will directly SFTP into servers sometimes to edit .htaccess files, which are sometimes on my production sites and dev sites and that I generally .gitignore.

Anyways, I think this is a fun thing to talk about, so feel free to have at it in the comments. I'd love to hear to what degree you cowboy code. Still do it all the time and love it? Do you do it because you haven't learned another way or that's how your workplace demands? Do you have a personal philosophy about it? Let the rodeo begin. &#x1f920;

The post When’s the last time you SFTP’d (or the like) into a server and changed a file directly? appeared first on CSS-Tricks.

Get References from HTML Built with Template Literals

Css Tricks - Thu, 11/08/2018 - 1:44pm

One thing JavaScript template literals are great at is little blocks of HTML. Like:

// Probably from some API or whatever const data = { title: "Title", content: "Content" }; const some_html = ` <div class="module"> <h2>${data.title}</h2> <p>${data.content}</p> </div> `;

But that's still just a string. It's not ready to append to the DOM just yet. And what if we need references to those elements inside somehow?

We've written about a couple of libraries that are in this vein: lit-html and hyperHTML. Those are pretty small libs, but are also sorta more about re-rendering of templates in an efficient way (like super mini React).

What if you just need the nodes? That's almost a one-liner:

const getNodes = str => { return new DOMParser().parseFromString(str, 'text/html').body.childNodes; }

Now we could drop that template literal of HTML right into the DOM:

document.body.appendChild(getNodes(some_html)[0]);

Here's that:

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

But how do we get our hands on individual bits of that HTML? We don't exactly have references to anything, even the whole chunk we put in.

I just saw this little lib called Facon that looks to do just this. It makes use of tagged template literals, which is super cool:

import f from 'facon'; const data = { title: "Title", content: "Content" }; let html = f` <div class="module"> <h2>${data.title}</h2> <p>${data.content}</p> </div> `; document.body.appendChild(html);

This skips the need for our little getNodes function, but more importantly, we can yank out those references!

let html = f` <div class="module"> <h2 ref="title">${data.title}</h2> <p ref="content">${data.content}</p> </div> `; let { title, content } = html.collect(); title.innerText = "Title Changed!";

Here's that:

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

The post Get References from HTML Built with Template Literals appeared first on CSS-Tricks.

CSS-Tricks Uses Jetpack

Css Tricks - Thu, 11/08/2018 - 1:12pm

(This is a sponsored post.)

Hey! I made a little page to explain all the ways in which this very site uses the Jetpack WordPress plugin.

Here's the gist of it:

  • Our Jetpack subscription gives us VaultPress, which backs up literally everything on this site in real time. That helps me sleep.
  • Jetpack improves our site search and allows it to be tweaked and the design customized.
  • Jetpack connects to Twitter and Facebook, so as we publish posts it can kick out tweets and updates.
  • Jetpack allows us to author content in Markdown (and you to comment in Markdown).
  • Jetpack adds social login buttons to the comment form, so you don't have to be troubled to type out your name and email.
  • We display related posts on articles, and Jetpack does a crack job of it without stressing out our server.

But Jetpack has way more features than that. That's just what we use, what you might find useful for your site could be totally different.

Direct Link to ArticlePermalink

The post CSS-Tricks Uses Jetpack appeared first on CSS-Tricks.

A Guide to Custom Elements for React Developers

Css Tricks - Thu, 11/08/2018 - 4:59am

I had to build a UI recently and (for the first time in a long while) I didn't have the option of using React.js, which is my preferred solution for UI these days. So, I looked at what the built-in browser APIs had to offer and saw that using custom elements (aka Web Components) may just be the remedy that this React developer needed.

Custom elements can offer the same general benefits of React components without being tied to a specific framework implementation. A custom element gives us a new HTML tag that we can programmatically control through a native browser API.

Let's talk about the benefits of component-based UI:

  • Encapsulation - concerns scoped to that component remain in that component's implementation
  • Reusability - when the UI is separated into more generic pieces, they're easier to break into patterns that you're more likely to repeat
  • Isolation - because components are designed to be encapsulated and with that, you get the added benefit of isolation, which allows you scope bugs and changes to a particular part of your application easier
Use cases

You might be wondering who is using custom elements in production. Notably:

  • GitHub is using custom elements for their modal dialogs, autocomplete and display time.
  • YouTube's new web app is built with Polymer and web components.
Similarities to the Component API

When trying to compare React Components versus custom elements, I found the APIs really similar:

  • They're both classes that aren't "new" and are able that extend a base class
  • They both inherit a mounting or rendering lifecycle
  • They both take static or dynamic input via props or attributes
Demo

So, let's build a tiny application that lists details about a GitHub repository.

If I were going to approach this with React, I would define a simple component like this:

<Repository name="charliewilco/obsidian" />

This component takes a single prop — the name of the repository — and we implement it like this:

class Repository extends React.Component { state = { repo: null }; async getDetails(name) { return await fetch(`https://api.github.com/repos/${name}`, { mode: 'cors' }).then(res => res.json()); } async componentDidMount() { const { name } = this.props; const repo = await this.getDetails(name); this.setState({ repo }); } render() { const { repo } = this.state; if (!repo) { return <h1>Loading</h1>; } if (repo.message) { return <div className="Card Card--error">Error: {repo.message}</div>; } return ( <div class="Card"> <aside> <img width="48" height="48" class="Avatar" src={repo.owner.avatar_url} alt="Profile picture for ${repo.owner.login}" /> </aside> <header> <h2 class="Card__title">{repo.full_name}</h2> <span class="Card__meta">{repo.description}</span> </header> </div> ); } }

See the Pen React Demo - GitHub by Charles (@charliewilco) on CodePen.

To break this down further, we have a component that has its own state, which is the repo details. Initially, we set it to be null because we don't have any of that data yet, so we'll have a loading indicator while the data is fetched.

During the React lifecycle, we'll use fetch to go get the data from GitHub, set up the card, and trigger a re-render with setState() after we get the data back. All of these different states the UI takes are represented in the render() method.

Defining / Using a Custom Element

Doing this with custom elements is a little different. Like the React component, our custom element will take a single attribute — again, the name of the repository — and manage its own state.

Our element will look like this:

<github-repo name="charliewilco/obsidian"></github-repo> <github-repo name="charliewilco/level.css"></github-repo> <github-repo name="charliewilco/react-branches"></github-repo> <github-repo name="charliewilco/react-gluejar"></github-repo> <github-repo name="charliewilco/dotfiles"></github-repo>

See the Pen Custom Elements Demo - GitHub by Charles (@charliewilco) on CodePen.

To start, all we need to do to define and register a custom element is create a class that extends the HTMLElement class and then register the name of the element with customElements.define().

class OurCustomElement extends HTMLElement {} window.customElements.define('our-element', OurCustomElement);

And we can call it:

<our-element></our-element>

This new element isn't very useful, but with custom elements, we get three methods to expand the functionality of this element. These are almost analogous to React’s lifecycle methods for their Component API. The two lifecycle-like methods most relevant to us are the disconnectedCallBack and the connectedCallback and since this is a class, it comes with a constructor.

Name Called when constructor An instance of the element is created or upgraded. Useful for initializing state, settings up event listeners, or creating Shadow DOM. See the spec for restrictions on what you can do in the constructor. connectedCallback The element is inserted into the DOM. Useful for running setup code, such as fetching resources or rendering UI. Generally, you should try to delay work until this time disconnectedCallback When the element is removed from the DOM. Useful for running clean-up code.

To implement our custom element, we'll create the class and set up some attributes related to that UI:

class Repository extends HTMLElement { constructor() { super(); this.repoDetails = null; this.name = this.getAttribute("name"); this.endpoint = `https://api.github.com/repos/${this.name}` this.innerHTML = `<h1>Loading</h1>` } }

By calling super() in our constructor, the context of this is the element itself and all the DOM manipulation APIs can be used. So far, we've set the default repository details to null, gotten the repo name from element's attribute, created an endpoint to call so we don't have to define it later and, most importantly, set the initial HTML to be a loading indicator.

In order to get the details about that element’s repository, we’re going to need to make a request to GitHub’s API. We’ll use fetch and, since that's Promise-based, we'll use async and await to make our code more readable. You can learn more about the async/await keywords here and more about the browser's fetch API here. You can also tweet at me to find out whether I prefer it to the Axios library. (Hint, it depends if I had tea or coffee with my breakfast.)

Now, let's add a method to this class to ask GitHub for details about the repository.

class Repository extends HTMLElement { constructor() { // ... } async getDetails() { return await fetch(this.endpoint, { mode: "cors" }).then(res => res.json()); } }

Next, let's use the connectedCallback method and the Shadow DOM to use the return value from this method. Using this method will do something similar as when we called Repository.componentDidMount() in the React example. Instead, we'll override the null value we initially gave this.repoDetails — we'll use this later when we start to call the template to create the HTML.

class Repository extends HTMLElement { constructor() { // ... } async getDetails() { // ... } async connectedCallback() { let repo = await this.getDetails(); this.repoDetails = repo; this.initShadowDOM(); } initShadowDOM() { let shadowRoot = this.attachShadow({ mode: "open" }); shadowRoot.innerHTML = this.template; } }

You'll notice that we're calling methods related to the Shadow DOM. Besides being a rejected title for a Marvel movie, the Shadow DOM has its own rich API worth looking into. For our purposes, though, it's going to abstract the implementation of adding innerHTML to the element.

Now we're assigning the innerHTML to be equal to the value of this.template. Let's define that now:

class Repository extends HTMLElement { get template() { const repo = this.repoDetails; // if we get an error message let's show that back to the user if (repo.message) { return `<div class="Card Card--error">Error: ${repo.message}</div>` } else { return ` <div class="Card"> <aside> <img width="48" height="48" class="Avatar" src="${repo.owner.avatar_url}" alt="Profile picture for ${repo.owner.login}" /> </aside> <header> <h2 class="Card__title">${repo.full_name}</h2> <span class="Card__meta">${repo.description}</span> </header> </div> ` } } }

That's pretty much it. We've defined a custom element that manages its own state, fetches its own data, and reflects that state back to the user while giving us an HTML element to use in our application.

After going through this exercise, I found that the only required dependency for custom elements is the browser's native APIs rather than a framework to additionally parse and execute. This makes for a more portable and reusable solution with similar APIs to the frameworks you already love and use to make your living.

There are drawbacks of using this approach, of course. We're talking about various browser support issues and some lack of consistency. Plus, working with DOM manipulation APIs can be very confusing. Sometimes they are assignments. Sometimes they are functions. Sometimes those functions take a callback and sometimes they don't. If you don't believe me, take a look at adding a class to an HTML element created via document.createElement(), which is one of the top five reasons to use React. The basic implementation isn’t that complicated but it is inconsistent with other similar document methods.

The real question is: does it even out in the wash? Maybe. React is still pretty good at the things it's designed to be very very good at: the virtual DOM, managing application state, encapsulation, and passing data down the tree. There's next to no incentive to use custom elements inside that framework. Custom elements, on the other hand, are simply available by virtue of building an application for the browser.

Learn more

The post A Guide to Custom Elements for React Developers appeared first on CSS-Tricks.

Simplify Styling with Functional CSS

Css Tricks - Wed, 11/07/2018 - 8:35am

There is no doubt that "functional CSS" resonates strongly with some people. If that term is new to you, I belive it's come to mean the same thing as "Atomic CSS" as defined by John Polacek here. Harry Nicholls likens it to a function that can only produce one result (although I'd call that a pure function or pure component), but instead of a return value being entirely predictable based on inputs, it is an application of style that only does one thing.

I'm of two minds here. People say how fast they can work this way. Great! They like how predictable the applied styles are. Great! I can understand how a tiny stylesheet that doesn't grow over time is appealing as well.

At the same time, I haven't seen writing about other styling concerns. What happens with big redesigns? Is it about the same, time- and difficulty-wise, or do you spend more time tearing down all those classes? What happens when you need a style that isn't available? Write your own? Or does that ruin the spirit of all this and put you in dangerous territory? How intense can all the class names get? I can think of areas I've styled that have three or more media queries that dramatically re-style an element. Putting all that information in HTML seems like it could get awfully messy. Is consistency harder or easier? I get that "p5" might be a useful way to apply an abstract amount of padding, but you still need to sprinkle it all over your codebase and know when to use it, right?

The closest I've been to being convinced about it was hearing from Adam just how configurable Tailwind is. In any case, I find this all endless fascinating and, if you love it, more power to ya.

Direct Link to ArticlePermalink

The post Simplify Styling with Functional CSS appeared first on CSS-Tricks.

Building a Donut Chart with Vue and SVG

Css Tricks - Wed, 11/07/2018 - 4:49am

Mmm... forbidden donut."

- Homer Simpson

I recently needed to make a donut chart for a reporting dashboard at work. The mock-up that I got looked something like this:

My chart had a few basic requirements. It needed to:

  • Dynamically calculate its segments based on an arbitrary set of values
  • Have labels
  • Scale well across all screen sizes and devices
  • Be cross-browser compatible back to Internet Explorer 11
  • Be accessible
  • Be reusable across my work’s Vue.js front end

I also wanted something that I could animate later if I needed to. All of this sounded like a job for SVG.

SVGs are accessible out-of-the-box (the W3C has a whole section on this) and can be made more accessible through additional input. And, because they’re powered by data, they’re a perfect candidate for dynamic visualization.

There are plenty of articles on the topic, including two by Chris (here and here) and a super recent one by Burke Holland. I didn’t use D3 for this project because the application didn’t need the overhead of that library.

I created the chart as a Vue component for my project, but you could just as easily do this with vanilla JavaScript, HTML, and CSS.

Here’s the finished product:

See the Pen Vue Donut Chart - Final Version by Salomone Baquis (@soluhmin) on CodePen.

Reinventing the wheel circle

Like any self-respecting developer, the first thing I did was Google to see if someone else had already made this. Then, like same said developer, I scrapped the pre-built solution in favor of my own.

The top hit for "SVG donut chart" is this article, which describes how to use stroke-dasharray and stroke-dashoffset to draw multiple overlaid circles and create the illusion of a single segmented circle (more on this shortly).

I really like the overlay concept, but found recalculating both stroke-dasharray and stroke-dashoffset values confusing. Why not set one fixed stroke-dasharrary value and then rotate each circle with a transform? I also needed to add labels to each segment, which wasn’t covered in the tutorial.

Drawing a line

Before we can create a dynamic donut chart, we first need to understand how SVG line drawing works. If you haven’t read Jake Archibald’s excellent Animated Line Drawing in SVG. Chris also has a good overview.

Those articles provide most of the context you’ll need, but briefly, SVG has two presentation attributes: stroke-dasharray and stroke-dashoffset.

stroke-dasharray defines an array of dashes and gaps used to paint the outline of a shape. It can take zero, one, or two values. The first value defines the dash length; the second defines the gap length.

stroke-dashoffset, on the other hand, defines where the set of dashes and gaps begins. If the stroke-dasharray and the stroke-dashoffset values are the length of the line and equal, the entire line is visible because we’re telling the offset (where the dash-array starts) to begin at the end of the line. If the stroke-dasharray is the length of the line, but the stroke-dashoffset is 0, then the line is invisible because we’re offsetting the rendered part of the dash by its entire length.

Chris’ example demonstrates this nicely:

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

How we’ll build the chart

To create the donut chart’s segments, we’ll make a separate circle for each one, overlay the circles on top of one another, then use stroke, stroke-dasharray, and stroke-dashoffset to show only part of the stroke of each circle. We’ll then rotate each visible part into the correct position, creating the illusion of a single shape. As we do this, we’ll also calculate the coordinates for the text labels.

Here’s an example demonstrating these rotations and overlays:

See the Pen Circle Overlays by Salomone Baquis (@soluhmin) on CodePen.

Basic setup

Let’s start by setting up our structure. I’m using x-template for demo purposes, but I’d recommend creating a single file component for production.

<div id="app"> <donut-chart></donut-chart> </div> <script type="text/x-template" id="donutTemplate"> <svg height="160" width="160" viewBox="0 0 160 160"> <g v-for="(value, index) in initialValues"> <circle :cx="cx" :cy="cy" :r="radius" fill="transparent" :stroke="colors[index]" :stroke-width="strokeWidth" ></circle> <text></text> </g> </svg> </script> Vue.component('donutChart', { template: '#donutTemplate', props: ["initialValues"], data() { return { chartData: [], colors: ["#6495ED", "goldenrod", "#cd5c5c", "thistle", "lightgray"], cx: 80, cy: 80, radius: 60, sortedValues: [], strokeWidth: 30, } } }) new Vue({ el: "#app", data() { return { values: [230, 308, 520, 130, 200] } }, });

With this, we:

  • Create our Vue instance and our donut chart component, then tell our donut component to expect some values (our dataset) as props
  • Establish our basic SVG shapes: <circle> for the segments and <text> for the labels, with the basic dimensions, stroke width, and colors defined
  • Wrap these shapes in a <g> element, which groups them together
  • Add a v-for loop to the g> element, which we’ll use to iterate through each value that the component receives
  • Create an empty sortedValues array, which we’ll use to hold a sorted version of our data
  • Create an empty chartData array, which will contain our main positioning data
Circle length

Our stroke-dasharray should be the length of the entire circle, giving us an easy baseline number which we can use to calculate each stroke-dashoffset value. Recall that the length of a circle is its circumference and the formula for circumference is 2?r (you remember this, right?).

We can make this a computed property in our component.

computed: { circumference() { return 2 * Math.PI * this.radius } }

...and bind the value to our template markup.

<svg height="160" width="160" viewBox="0 0 160 160"> <g v-for="(value, index) in initialValues"> <circle :cx="cx" :cy="cy" :r="radius" fill="transparent" :stroke="colors[index]" :stroke-width="strokeWidth" :stroke-dasharray="circumference" ></circle> <text></text> </g> </svg>

In the initial mockup, we saw that the segments went from largest to smallest. We can make another computed property to sort these. We’ll store the sorted version inside the sortedValues array.

sortInitialValues() { return this.sortedValues = this.initialValues.sort((a,b) => b-a) }

Finally, in order for these sorted values to be available to Vue before the chart gets rendered, we’ll want to reference this computed property from the mounted() lifecycle hook.

mounted() { this.sortInitialValues }

Right now, our chart look like this:

See the Pen Donut Chart - No Segments by Salomone Baquis (@soluhmin) on CodePen.

No segments. Just a solid-colored donut. Like HTML, SVG elements are rendered in the order that they appear in the markup. The color that appears is the stroke color of the last circle in the SVG. Because we haven’t added any stroke-dashoffset values yet, each circle’s stroke goes all the way around. Let’s fix this by creating segments.

Creating segments

To get each of the circle segments, we’ll need to:

  1. Calculate the percentage of each data value from the total data values that we pass in
  2. Multiply this percentage by the circumference to get the length of the visible stroke
  3. Subtract this length from the circumference to get the stroke-offset

It sounds more complicated than it is. Let’s start with some helper functions. We first need to total up our data values. We can use a computed property to do this.

dataTotal() { return this.sortedValues.reduce((acc, val) => acc + val) },

To calculate the percentage of each data value, we’ll need to pass in values from the v-for loop that we created earlier, which means that we’ll need to add a method.

methods: { dataPercentage(dataVal) { return dataVal / this.dataTotal } },

We now have enough information to calculate our stroke-offset values, which will establish our circle segments.

Again, we want to: (a) multiply our data percentage by the circle circumference to get the length of the visible stroke, and (b) subtract this length from the circumference to get the stroke-offset.

Here’s the method to get our stroke-offsets:

calculateStrokeDashOffset(dataVal, circumference) { const strokeDiff = this.dataPercentage(dataVal) * circumference return circumference - strokeDiff },

...which we bind to our circle in the HTML with:

:stroke-dashoffset="calculateStrokeDashOffset(value, circumference)"

And voilà! We should have something like this:

See the Pen Donut Chart - No Rotations by Salomone Baquis (@soluhmin) on CodePen.

Rotating segments

Now the fun part. All of segments begin at 3 o’clock, which is the default starting point for SVG circles. To get them in the right place, we need to rotate each segment to its correct position.

We can do this by finding each segment’s ratio out of 360 degrees and then offset that amount by the total degrees that came before it.

First, let’s add a data property to keep track of the offset:

angleOffset: -90,

Then our calculation (this is a computed property):

calculateChartData() { this.sortedValues.forEach((dataVal, index) => { const data = { degrees: this.angleOffset, } this.chartData.push(data) this.angleOffset = this.dataPercentage(dataVal) * 360 + this.angleOffset }) },

Each loop creates a new object with a "degrees" property, pushes that into our chartValues array that we created earlier, and then updates the angleOffset for the next loop.

But wait, what’s up with the -90 value?

Well, looking back at our original mockup, the first segment is shown at the 12 o’clock position, or -90 degrees from the starting point. By setting our angleOffset at -90, we ensure that our largest donut segment starts from the top.

To rotate these segments in the HTML, we’ll use the transform presentation attribute with the rotate function. Let’s create another computed property so that we can return a nice, formatted string.

returnCircleTransformValue(index) { return rotate(${this.chartData[index].degrees}, ${this.cx}, ${this.cy})` },

The rotate function takes three arguments: an angle of rotation and x and y coordinates around which the angle rotates. If we don’t supply cx and cy coordinates, then our segments will rotate around the entire SVG coordinate system.

Next, we bind this to our circle markup.

:transform="returnCircleTransformValue(index)"

And, since we need to do all of these calculations before the chart is rendered, we’ll add our calculateChartData computed property in the mounted hook:

mounted() { this.sortInitialValues this.calculateChartData }

Finally, if we want that sweet, sweet gap between each segment, we can subtract two from the circumference and use this as our new stroke-dasharray.

adjustedCircumference() { return this.circumference - 2 }, :stroke-dasharray="adjustedCircumference"

Segments, baby!

See the Pen Donut Chart - Segments Only by Salomone Baquis (@soluhmin) on CodePen.

Labels

We have our segments, but now we need to create labels. This means that we need to place our <text> elements with x and y coordinates at different points along the circle. You might suspect that this requires math. Sadly, you are correct.

Fortunately, this isn’t the kind of math where we need to apply Real Concepts; this is more the kind where we Google formulas and don’t ask too many questions.

According to the Internet, the formulas to calculate x and y points along a circle are:

x = r cos(t) + a y = r sin(t) + b

...where r is the radius, t is the angle, and a and b are the x and y center point offsets.

We already have most of this: we know our radius, we know how to calculate our segment angles, and we know our center offset values (cx and cy).

There’s one catch, though: in those formulas, t is in *radians*. We’re working in degrees, which means that we need to do some conversions. Again, a quick search turns up a formula:

radians = degrees * (? / 180)

...which we can represent in a method:

degreesToRadians(angle) { return angle * (Math.PI / 180) },

We now have enough information to calculate our x and y text coordinates:

calculateTextCoords(dataVal, angleOffset) { const angle = (this.dataPercentage(dataVal) * 360) / 2 + angleOffset const radians = this.degreesToRadians(angle) const textCoords = { x: (this.radius * Math.cos(radians) + this.cx), y: (this.radius * Math.sin(radians) + this.cy) } return textCoords },

First, we calculate the angle of our segment by multiplying the ratio of our data value by 360; however, we actually want half of this because our text labels are in the middle of the segment rather than the end. We need to add the angle offset like we did when we created the segments.

Our calculateTextCoords method can now be used in the calculateChartData computed property:

calculateChartData() { this.sortedValues.forEach((dataVal, index) => { const { x, y } = this.calculateTextCoords(dataVal, this.angleOffset) const data = { degrees: this.angleOffset, textX: x, textY: y } this.chartData.push(data) this.angleOffset = this.dataPercentage(dataVal) * 360 + this.angleOffset }) },

Let’s also add a method to return the label string:

percentageLabel(dataVal) { return `${Math.round(this.dataPercentage(dataVal) * 100)}%` },

And, in the markup:

<text :x="chartData[index].textX" :y="chartData[index].textY">{{ percentageLabel(value) }}</text>

Now we’ve got labels:

See the Pen Donut Chart - Unformatted Labels by Salomone Baquis (@soluhmin) on CodePen.

Blech, so off-center. We can fix this with the text-anchor presentation attribute. Depending on your font and font-size, you may want to adjust the positioning as well. Check out dx and dy for this.

Revamped text element:

<text text-anchor="middle" dy="3px" :x="chartData[index].textX" :y="chartData[index].textY">{{ percentageLabel(value) }}</text>

Hmm, it seems that if we have small percentages, the labels go outside of the segments. Let’s add a method to check for this.

segmentBigEnough(dataVal) { return Math.round(this.dataPercentage(dataVal) * 100) > 5 } <text v-if="segmentBigEnough(value)" text-anchor="middle" dy="3px" :x="chartData[index].textX" :y="chartData[index].textY">{{ percentageLabel(value) }}</text>

Now, we’ll only add labels to segments larger than 5%.

And we’re done! We now have a reusable donut chart component that can accept any set of values and create segments. Super cool!

The finished product:

See the Pen Vue Donut Chart - Final Version by Salomone Baquis (@soluhmin) on CodePen.

Next steps

There are lots of ways that we can modify or improve this now that it’s built. For example:

  • Adding elements to enhance accessibility, such as <title> and <desc> tags, aria-labels, and aria role attributes.
  • Creating animations with CSS or libraries like Greensock to create eye-catching effects when the chart comes into view.
  • Playing with color schemes.

I’d love to hear what you think about this implementation and other experiences you’ve had with SVG charts. Share in the comments!

The post Building a Donut Chart with Vue and SVG appeared first on CSS-Tricks.

Fun Tip: Use calc() to Change the Height of a Hero Component

Css Tricks - Tue, 11/06/2018 - 4:51am

The concept of Fluid Typography was tossed around a couple of years ago. The main idea is that if you know what size your font is at two different viewport sizes, then you can have the font scaling smoothly between the two sizes. We had a jQuery solution for this in FitText (meant of headings, of course) until the calc() function was shipped giving us a pure CSS solution.

p { font-size: calc(16px + (24 - 16)*(100vw - 400px)/(800 - 400)); }

See the Pen Fluid Typography by Martino Stenta (@martinostenta) on CodePen.

The important numbers here are 24px (the larger font up to 800px viewports) and 16px (the smaller font size down to 400px viewports). I wouldn’t use the terms "minimum" or "maximum" to describe font sizes and viewports in this context because it is a little misleading. In fact, you still need to provide a default font size for viewports smaller than 400px and bigger than 800px — otherwise, the font will keep getting smaller (or bigger) with the same scale of the equation. Or, if you are fancy, you could define another scale for bigger screen sizes.

See the Pen Fluid Typography with reset size by Martino Stenta (@martinostenta) on CodePen.

It works really well and you should definitely check the math behind this.

Padding and line height?

I liked the concept of Fluid Typography so much that I asked myself if it could work with other properties. And it does! You can’t use a percentage, but as long as you stick with px, em or rem units, then it’s OK. I’m a pixel guy, so all my experiments have used those, but there is this neat generatorthat helps you with conversions if you need it.

So, back to padding and line-height. Using the same calc() logic, we can achieve a fully fluid *layout* with fixed values for defined screen sizes.

See the Pen Pure CSS Variable Padding, Font Size and Line Height by Martino Stenta (@martinostenta) on CodePen.

I implemented this idea on this website, but kept it to font-size and line-height. And, yes, it gets easier to look past all that math and put to use the more you work with it.

See the Pen Working Example of calc() on font-size and line-hieght by Martino Stenta (@martinostenta) on CodePen.

A digression about "Hero" components

If you’re like me, then you might take issue with what we all have come to know as the hero component. It’s ubiquitous to the extent that it’s become a staple in design systems (like Bootstrap) and you may have even seen it satirized on sites like this.

My main gripe concerns the best way to make them responsive. If it’s not a *full screen* hero (i.e. takes over the entire viewport at any size), then I usually ask the designer how the page should behave. There’s often a proportion of the hero page that works fine, so that allows me to use padding-bottom in % with absolute positioning of the inner content. That tactic works most of the time,

This is fun and it works fine especially on the desktop version of a website. You end up with a neat hero section, the proportion is good and the content is centered.

See the Pen Standard hero section with 'padding-bottom' by Martino Stenta (@martinostenta) on CodePen.

But what happens when you start shrinking the viewport? The hero remains readable up to a point, you really need to change the proportion.

Assuming we are working with a desktop-first responsive approach, we could start with a horizontal rectangle that scales down to the point where we’re left with a vertical rectangle on small screens.

Hero component with different proportions based on device

This is a PITA because you could end up with many lines of CSS to have a nice and readable hero section at various breakpoints.

There has to be a better way, right? What if the hero could increase its height while the page width gets narrower?

Back to fluidity!

So, I turned back to the calc() function that worked in those other situations, like making the browser handle the math and scale things accordingly as the viewport changes.

Here’s the CSS from the Fluid Typography example we started with:

p { width: 100%; max-width: 1200px; margin: 0 auto; font-family: 'Open Sans', sans-serif; font-size: calc(24px + (18 - 24)*(100vw - 400px)/(1200 - 400)); line-height: 1.5; padding: 10px; }

Here’s what we want: a hero component that gets bigger while you shrink the page. I used pixel units for the fluid part and percentages everywhere else.

Here’s a screencast of how the solution I landed on:

Live Demo

This is pretty useful when you want to give more vertical space to the text. Shrinking the viewport width from large to small will end up having more lines for the same text, since the font size can’t be too small.

See the Pen Hero section with calc() by Martino Stenta (@martinostenta) on CodePen.

Pretty nice, right? Yet another way calc() proved it could solve a scenario for me.

Yes, there are some caveats

Browser support is very good, tallying almost 93% of the users (at the time of writing), with the main exception being Opera mini.

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

DesktopChromeOperaFirefoxIEEdgeSafari19*154*10126*Mobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox6.0-6.1*46No676962

Also, remember that this calc() technique supports only px, em, and rem units. But the examples we covered here are pretty easy to convert units for things like padding-bottom percentages to pixels since the hero is typically 100% in width.

Oh! And remember to reset your values before and after the breakpoints in the calc() function. Otherwise you’ll end up with either very big or very small values for the target properties.

What say you?

This is probably just one way we can handle the situation and it was primarily driven by my interest in the calc() function. So, that begs the question: how have you handled scaling hero component height? Have you put calc() to use for it? Do you prefer wrangling breakpoints at various widths? Is there something else you use? Light up the comments!

The post Fun Tip: Use calc() to Change the Height of a Hero Component appeared first on CSS-Tricks.

How we made Carousell’s mobile web experience 3x faster

Css Tricks - Tue, 11/06/2018 - 4:50am

Both a sobering and interesting read from Stacey Tay on how the team at Carousell gathered the metrics to define a performance budget and, in turn, developed a better experience for their customers:

Our new PWA listing page loads 3x faster than our old listing page. After releasing this new page, we’ve had a 63% increase in organic traffic from Indonesia, compared to our our all time-high week. Over a 3 week period, we also saw a 3x increase in ads click-through-rates and a 46% increase in anonymous users who initiated a chat on the listing page.

The team inlined critical CSS, reduced the number of resources the app was loading, and implemented a lazy loading strategy, among many other things. I think it’s interesting to note that they also changed the design of the app in certain ways to make things more performant, too. I reckon it’s easy to fall into the trap of thinking that performance is solely a task for developers and posts like this prove that it's more collaborative than that.

Direct Link to ArticlePermalink

The post How we made Carousell’s mobile web experience 3x faster appeared first on CSS-Tricks.

Conversions: PWAs, Payment Experiences and More

LukeW - Mon, 11/05/2018 - 2:00pm

In her PWAs, Payment Experiences and More presentation at Google Conversions 2018 in Dublin Ireland, Jenny Gove talked through the new capabilities available on the Web to build fast and engaging products. Here's my notes from her talk:

  • The Web was built for desktop devices, not mobile. Native apps, in contrast, were built from the ground up for mobile. So it's no surprise that Web sites are still catching up in terms of experience. While there are great mobile Web experiences, most have a lot of work to do.
  • To help incentivize people to improve mobile Web experiences, Google added the "mobile-friendly" label to search results. When 85% of results in mobile search met this criteria, the label was removed.
  • Progressive Web apps bring richer experiences to the Web through a set of technologies that enable fast, installable, reliable, and engaging. They're the next step in making great Web experiences.
  • Speed is critical for mobile Web sites but it takes a mobile Web page a median time of 9.3 seconds to load on 3G. Pinterest reduced their time for interactive from 23 seconds to 5.6 seconds with their PWA. This resulted in a 60% increase in engagement and a 2-3% improvement over their native app.
  • You can improve speed with technical changes and design (to manage perception). Lighthouse is a tool from Google that shows time to meaningful paint and other relevant metrics for improving technical performance. You can manage user perception of speed using skeletong screens and gradual loading of content.
  • PWAs allow you to add mobile Web pages to your phone's home screens. On Android these apps show up in app switchers and setting screens.
  • Service workers in PWAs enable reliable experiences when there is no network or slow and intermittent network connections. Even in developed markets, slow network conditions often exist. Service workers are now available in all major Web browsers.
  • PWAs make use of Web technologies at the right time and place like app permissions, push notifications, payment request APIs, and better form interactions (autocomplete, input types, etc.)
  • 42% of top sites in Europe don't show the appropriate keyboard for specific input types. 27% of the top site in Europe didn't identify which form fields are optional.
  • Google Search uses a PWA to enable offline queries and send results when people are back online using notifications. With a PWA they were able to use 50% fewer external JavaScript requests.
  • In the Starbucks PWA, daily & monthly active users have nearly doubled (compared ot the previous Web experience) and orders placed in the PWA are growing by more than 12% week over week.
  • While mobile has really driven PWA requirements, desktop devices also benefit from PWA app switching and integration. Service workers, push notifications, and other new Web technologies work on desktop as well.
  • It's possible to run PWAs on the desktop in app windows which can be themed. These apps need to use responsive design to adapt from small sized windows to full-sized screens.
  • What's next for PWAs? Support for Windows, macOS and Linux, Keyboard Shortcuts, Badging the launch icon, and Link capturing.

Rocking California’s “I Voted” Sticker in CSS for Election Day 2018

Css Tricks - Mon, 11/05/2018 - 4:54am

Oh hey, so tomorrow (tomorrow!) is Election Day here in the United States. We're not in the business of making political endorsements or anything like that at CSS-Tricks, though we do endorse that everyone exercise their right to vote.

I did exactly that two years ago and posted a CSS rendition of the "I Voted" sticker that came with my California mail-in ballot.

See the Pen I Voted Sticker by Geoff Graham (@geoffgraham) on CodePen.

Fast forward to today, and I received a new sticker in the ballot sporting a fresh design:

Credit: Los Angeles Magazine (source)

I have a little time, so I'm going to try to re-create this sticker in CSS and walk through my thought process as I do it. Feel free to follow along if you'd like!

Breaking down the elements

Anytime I'm given a design of any kind, I like to pretend that my eyes have the superpower of X-ray vision and can see through the design as if it were a skeleton. This helps me start to think through how many elements I might use in the HTML.

OK, I think I'm going to start with something like this:

<!-- Main Circle --> <div class="sticker"> <div class="sticker__top"> <!-- Will use ::before and ::after to create halves --> <h1>I Voted</h1> </div> <div class="sticker__bottom"> <!-- The list of languages --> <ul> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> <li>Item</li> </ul> </div> </div>

I'm also going to throw in some base styles on the <body> so I can jump right into the rest of the sticker.

See the Pen "I Voted" Sticker HTML by Geoff Graham (@geoffgraham) on CodePen.

OK, nothing fancy so far. Really just looks like an unordered list with a heading with some terrible contrast between the content and background.

Working on the main sticker container

I think I'll set up the container, which is the main circle. I'm going to use a fixed width and height, then use border-radius to round it out and into the shape of a circle.

Oh, and I ought to take care of that dark text and also add a border while I'm at it, so I can see what I'm doing.

.sticker { border: 20px solid #fff; border-radius: 100%; color: #fff; height: 400px; width: 400px; }

See the Pen "I Voted" Sticker HTML 2 by Geoff Graham (@geoffgraham) on CodePen.

The alignment is all off. Seems like a good spot to drop in some flexbox. This will allow me to center our elements horizontally. I think going with a single-column layout will take care of the vertical alignment.

.sticker { display: flex; flex-flow: column; align-items: center; border: 20px solid #fff; border-radius: 100%; color: #fff; height: 400px; width: 400px; }

Yep, that helps.

See the Pen "I Voted" Sticker HTML 3 by Geoff Graham (@geoffgraham) on CodePen.

The last thing I want to do with the sticker for now is split it up into two halves — a top and a bottom. OK, so yeah, I have explicit elements for those in the HTML (.sticker__top and .sticker__bottom). I could use background-color on each element to make the top half blue and bottom half red, but I actually like the idea of using a linear gradient instead with a hard stop at the halfway mark.

.sticker { background-image: linear-gradient( to bottom, #080968, #080968 50%, #080968 50%, #F81616 50% ); border: 20px solid #fff; border-radius: 100%; color: #fff; display: flex; flex-flow: column; align-items: center; height: 400px; width: 400px; }

Hey now, looking much sharper already!

See the Pen "I Voted" Sticker HTML 4 by Geoff Graham (@geoffgraham) on CodePen.

Time to deal with the top half

The top and bottom halves both occupy 50% of the sticker's height, so the selectors can be combined to hit them both at once. Plus, I'm using flexbox, so I can simply flex those items.

.sticker__top, .sticker-bottom { flex: 0 50%; }

The top half is super weird. The way I see it, there's two rows: one that contains the stars and stripes and the other that contains the heading. I'm going to turn to flexbox again to draw that layout.

.sticker__top { display: flex; flex-flow: row wrap; position: relative; }

That's not really going to change much at the moment because, well, I haven't done anything to define elements for the stars and stripes in the HTML. I'm thinking of using the ::before and ::after pseudo elements on .sticker__top to make those. Again, they can be combined since they share some common properties and values.

.sticker__top::before, .sticker__top::after { content: ""; height: 45%; /* Had to play with this a bit */ margin-top: 2em; /* Move away from the top edge of the sticker */ }

I'm going to cheat and use SVG for the stars. I mean, I guess that's not cheating but it sorta feels like a deviation from a "pure" CSS way of doing things. Oh well.

That said, the stripes can definitely be made in CSS, again, with the same linear gradient background technique that's used to split the sticker up into blue and red halves.

.sticker__top::before { background-image: url("/path/to/star/image.svg"); background-size: 35px; /* Magic number, depends on the image used. */ } .sticker__top::after { background-image: linear-gradient( to bottom, #F81616, #F81616 14%, transparent 14%, transparent 28%, #F81616 28%, #F81616 42%, transparent 42%, transparent 56%, #F81616 56%, #F81616 70%, transparent 70%, transparent 84%, #F81616 84%, #F81616 98%, transparent 100% ); }

That's cool but, crap, things are out of order.

See the Pen "I Voted" Sticker HTML 5 by Geoff Graham (@geoffgraham) on CodePen.

I'm so thankful flexbox has an order property. I'm going to order the stars, stripes and heading at 1, 2 and 3, respectively,

.sticker__top::before { /* Same as before... */ order: 1; } .sticker__top::after { /* Same as before... */ order: 2; } .sticker__top h1 { order: 3; }

If I stop here, the shape of the stars and stripes would be all off and the heading font would be sloppy.

border-radius is still a good way to get the stars and stripes to follow the same circular path as the sticker. The rub is that the bottoms of them have to maintain a flat edge. Since border-radius is a shorthand property, I'm going to drop border-top-left-radius on the stars and border-top-right-radius on the stripes.

It's also worth noting that the stripes are a little wider than the stars. Maybe a 55-45 split? I don't know. I'll go with that and also use relative positioning on the stripes so I can push them to the right a bit to add separation between them and the stars.

.sticker__top::before { /* Same as before... */ flex: 45%; } .sticker__top::after { /* Same as before... */ flex: 55%; position: relative; left: 10px; }

The stars and stripes should flex with the size and width of the heading. I had to play with the font family, font size, letter spacing, and text transform to get something that looks pretty nice. In case you're wondering, I wound up using Raleway for the font. It's not precise, but close enough... at least to my untrained typographical eye.

.sticker__top h1 { font-family: 'Raleway', sans-serif; font-size: 4em; letter-spacing: 3px; line-height: 0; text-transform: uppercase; order: 3; }

See the Pen "I Voted" Sticker HTML 6 by Geoff Graham (@geoffgraham) on CodePen.

Alright, so now the bottom half is making my skin crawl. Gotta tackle that.

Style up the bottom half

So much has already been done. The element for bottom half is already there in the HTML and is sized and positioned the way it should be. I think stripping out the bullet points of the list items and removing the left padding from the unordered list will clean things up a lot.

.sticker__bottom ul { list-style: none; padding: 0; width: 100%; /* Gotta take up the all of the bottom half */ }

But, that's not going to cut it completely. I want that list to run horizontally, wrap lines, and to allow the list items to occupy open space. Yep, that sounds like flexbox again.

.sticker__bottom ul { display: flex; flex-flow: row wrap; align-items: flex-start; justify-content: flex-start; /* same as before... */ } .sticker__bottom li { flex: auto; /* Flex as much as you need, guys */ margin: .75em; /* A liiiiitle breathing room between items */ }

See the Pen "I Voted" Sticker HTML 7 by Geoff Graham (@geoffgraham) on CodePen.

Now I have to make a few tweaks to .sticker__bottom. Specifically, I'm going to make it a little narrower (80% of the full sticker width) to get it off the edge of the sticker and then round its edges... though it might not actually need rounded corners since content is not going to overflow.

.sticker__bottom { border-bottom-right-radius: 100%; border-bottom-left-radius: 100%; width: 80%; }

And, now center the text. I guess that can go on the parent .sticker element since nothing on the sticker is technically left-justified.

.sticker { /* same as before... */ text-align: center; }

Finally, I'm going to do my best to replace the dummy content with the "I Voted" translations. Let me go look those up.

(Heads over to Google Translate.)

Meh, I couldn't find everything I needed. I'm sure it's my lack of patience, but I wound up using some alternatives:

<ul> <li>Yo voté</li> <li>???</li> <li>?? ????</li> <li>Bumoto ako</li> <li>? ????????????</li> <li>???? ????? ????</li> <li>??? ????</li> <li>Ik stemde</li> <li>Szavaztam</li> <li>???????????</li> <li>Anigu waxaan codsaday</li> <li>Tôi ?ã b?u ch?n</li> </ul>

I'm going to have to play around with the font size and to get the same sort of alignment as the IRL sticker, which has rows of: 4 items, 3 items, 3 items, 1 item, 1 item.

Here's where I landed:

.sticker__bottom ul { display: flex; flex-flow: row wrap; font-size: .75em; align-items: flex-start; justify-content: flex-start; list-style: none; padding: 0; width: 100%; }

To get the last two items off the same line, I'm going to single out the second-to-last one using :last-child() so that both of them always flex 100%:

.sticker__bottom li:nth-child(11) { flex: 100%; }

And, lastly, I'm going to change the white border around the sticker from white to blue. Gives it that faux padding we're looking for.

See the Pen "I Voted" Sticker HTML 8 by Geoff Graham (@geoffgraham) on CodePen.

Ding, ready!

I'm going to call this one baked. I know, I know. I should cross-browser test. It would also be wise to find graceful fallbacks for older browsers that do not support flexbox. And, some responsiveness would be nice to have. Maybe someone would like to take those up and share. &#x1f609;

Is this the best way to make the sticker? Probably not. For example, I bet there are some interesting things that can be done with clip-path instead of the way I fumbled through background gradients. And, if I had to do it again, I might even consider going with a CSS Grid layout on the parent because there are clearly opportunities to work in two directions instead of one.

But that's the beauty of CSS. There's more than one way to accomplish something.

Happy Election Day, friends. &#x1f1fa;&#x1f1f8;

The post Rocking California’s “I Voted” Sticker in CSS for Election Day 2018 appeared first on CSS-Tricks.

What’s New In CSS?

Css Tricks - Fri, 11/02/2018 - 12:44pm

Rachel hooks us up with what the CSS Working Group is talking about:

  • Styling scrollbars. This would come with properties like scrollbar-width and scrollbar-color. The best we have right now is proprietary WebKit stuff.
  • Aspect ratios. I imagine the CSS portion of this journey will be best handled if it plays nicely with the HTML intrinsicsize stuff.
  • Matching without specificity. :where() is :matches() with no specificity, and :matches() may become :is().
  • Logical Properties shorthand. The team is discussing a shorthand syntax for Logical Properties and the possibility logical would be default over the current physical with a defined "mode" in the stylesheet.

Direct Link to ArticlePermalink

The post What’s New In CSS? appeared first on CSS-Tricks.

Simple Named Grid Areas

Css Tricks - Fri, 11/02/2018 - 4:02am

I think of named grid areas in CSS Grids as bring-your-own syntactic sugar. You don't absolutely need them (you could express grid placement in other ways), but it can make that placement more intuitive. And, hey, if I'm wrong about that, correct me in the comments.

Say you set up a 3-column grid:

.grid { display: grid; grid-gap: 1rem; grid-template-columns: 200px 1fr 1fr; }

No rows defined there; those are implicit and will appear as needed. We could define them, we just aren't, because like most situations in web design, we don't care how tall the items are — the height will grow as needed to accomodate the content.

Now, how do we place something in that very top-left position in the grid? We could tell the grid to place it there like this:

.item { grid-column: 1 / 2; /* start at the first grid column line and end at the second */ }

That works, although that .item better be the first child of .grid. Otherwise, something else may implicitly be placed there and .item will kick down to the next open row. If we wanted to be super sure to place it in the top-left, we could do the row as well:

.item { grid-column: 1 / 2; grid-row: 1 / 2; }

Now it will be in the top-left for sure, even if other items are explicitly placed there (they'll just overlap). We can even shorten things up with the grid-area property:

.item { grid-area: 1 / 1 / 2 / 2; }

All those 1's and 2's might be intuitive enough for now, but the numbers become a bit much in more complex grids involving both column and row placement.

Check this. While we are defining the columns, we can name them with a separate property:

.grid { display: grid; grid-gap: 1rem; grid-template-columns: 200px 1fr 1fr; grid-template-areas: "pro a b" "pro c d"; }

Every quoted group in grid-template-areas is a row. Inside are names I just made up. Could be just about anything, as long as it makes sense to you. See how the word "pro" is repeated twice there on two rows? That's important, as it's saying that we could place a grid item where that value "pro" is and it will be in the first of three columns and span two rows. Pretty intuitive, yeah?

We place it like this:

.pro-features { /* rather than */ grid-area: 1 / 1 / 2 / 3; /* we can now do */ grid-area: pro; }

Here's that simple example:

See the Pen Simple Named Grid Areas by Chris Coyier (@chriscoyier) on CodePen.

Want to get even more descriptive with a grid? Try drawing it in your CSS comments.

The post Simple Named Grid Areas appeared first on CSS-Tricks.

Understanding React Render Props and HOC

Css Tricks - Thu, 11/01/2018 - 9:25am

Here’s a great post by Aditya Agarwal on the difference between render props and higher-order components in React. I particularly like the demo he chose to explain the two. But, to summarize:

Higher-order components (HOCs) take a component and return a component. So let’s say you have a component called Username that just returns a string of a user’s name and you want to capitalize that somewhere – this is the perfect opportunity to use a HOC that wraps that Username component and changes each character. Just like the excellent tutorial Kingsley Silas wrote up here on CSS-Tricks.

HOCs are particularly useful for when you want to modify a component and then use it in a bunch of places, or to make tiny batches of code to prevent overwhelming a component with too many options and props.

A render prop on the other hand is “a function prop that a component uses to know what to render.” At least, that’s what the React docs say, but it took me a while to figure it out. As far as I understand, it lets you provide a way for a React component (typically one that just has a bunch of data you want to reuse) and give it to another (so a component that then renders that data).

here’s a great example of this in the React docs:

class MouseTracker extends React.Component { render() { return ( <div> <h1>Move the mouse around!</h1> <Mouse render={mouse => ( <Cat mouse={mouse} /> )}/> </div> ); } }

What’s happening here is that someone defined a Mouse component in the codebase that provides x + y coordinates based on the position of the user’s mouse. This Mouse component then returns a bunch of data that we store as mouse and then pass it down into the Cat component which is what renders something with that data.

This is great when you want to reuse the data from Mouse but also when you want to pass lots of different types of data into the Cat component. Say you want Cat to render something else based on the type of data you feed into it.

So, to summarize: HOCs and render props are two ways to do similar work. Namely, they can break our code into lots of reusable bits and encourage us to make components that are more flexible in the long run.

Direct Link to ArticlePermalink

The post Understanding React Render Props and HOC appeared first on CSS-Tricks.

Syndicate content
©2003 - Present Akamai Design & Development.