Web Standards

Weekly Platform News: Feature Policy, Signed Exchanges, iOS browsers

Css Tricks - Fri, 05/10/2019 - 4:22am

👋 Hey folks! This is the first edition of a new weekly update we'll be posting that covers timely news at the intersection of development standards and the tools that make them available on the web. We often talk about the pace of change in our industry. It's fast and touches everything from the HTML, CSS and JavaScript we write to the landscape of browsers that renders them. Please help us welcome Šime Vidas, who will be keeping us all on the up and up with curated updates from his own blog of regular development updates, webplatform.news.

Feature Policy in Chrome

Andrew Betts: Websites can use the HTTP Feature-Policy response header to prevent third parties from secretly using powerful features such as geolocation, and to disable certain bad practices (e.g. document.write, parser-blocking JavaScript, un-optimized images).

This allows good practices to be more easily rewarded. … Search results could be badged with some approving "fast" logomark or (more controversially perhaps) get a higher result ranking if they disallow themselves certain policy-controlled behaviors.

Feature Policy is an emerging technology. See featurepolicy.info for more information about individual policies and their level of support in browsers.

Signed exchanges on Google Search

The mobile version of Google Search includes AMP results on search results pages. When the user taps on an AMP result, the AMP page loads from Google’s domain (google.com) and is displayed in the AMP Viewer.

Google Search now supports an alternative: If a website signs its AMP pages, and the visitor uses Chrome for Android, then tapping on an AMP result instead loads the signed version of the AMP page from Google’s servers, but to the user it appears as if they have navigated to the website normally.

The technology that enables this is called Signed HTTP Exchanges (SXG). See the announcement on Google Webmaster Central Blog for more details. The specification describes the following use case:

In order to speed up loading but still maintain control over its content, an HTML page in a particular origin "O.com" could tell clients to load its sub-resources from an intermediate content distributor that’s not authoritative, but require that those resources be signed by "O.com" so that the distributor couldn’t modify the resources.

Websites can add support for signed exchanges by running AMP Packager on the server side. Cloudflare has launched a free feature called "AMP Real URL" that fully automates the signing process for AMP pages served from its CDN.

Alternative iOS browsers

Henrik Joreteg: On iOS, several important APIs are limited to Safari and are not available in any of the alternative iOS browsers. These include service workers, web payments, and camera access.

Chrome on iOS is such a pain. A surprising number of people seem to use it and no one realizes it's not actually Chrome but just a crippled webkit webview missing major features:

1. No Service Worker
2. Can't print or save as PDF
3. No support for GetUserMedia

Why is this OK?!

— Henrik Joreteg (@HenrikJoreteg) March 30, 2019

Chrome for iOS supports web payments via a custom implementation. I’ve created a browser support table on HTML5test that highlights the differences between some of the popular iOS browsers.

The post Weekly Platform News: Feature Policy, Signed Exchanges, iOS browsers appeared first on CSS-Tricks.

CSS-Tricks Chronicle XXXV

Css Tricks - Thu, 05/09/2019 - 2:55pm

I like to do these little roundups of things going on with myself, this site, and the other sites that are part of the CSS-Tricks family.

I spoke at Smashing Conf San Francisco.

There's a video! I can't embed it here because of privacy settings or something, so here's a link to the Vimeo.

It's an evolution of my "How To Think Like A Front-End Developer" talk. That's kinda how I like to roll with talks. Give the same one for about a year, but every time it's different as I learn more.

I was on the One Month podcast.

Chris Castiglione and I chat about:

  • How Chris Coyier learned to code
  • What’s a front-end developer?
  • What resources does Chris Coyier use to stay up to date on web dev?
  • Lessons learned from over 300+ episodes of the ShopTalkShow Podcast

There's a full transcript available.

We've released a number of new things on CodePen.

Quick hits:

And, as always on CodePen, we have a new CodePen Challenge, a new CodePen Spark (newsletter), and a new CodePen Radio (podcast) every single week.

I'm speaking at some upcoming conferences. The front-end conference website got some upgrades.

We keep a list of all conferences out there related to the topics we write about here on CSS-Tricks! All things front-end web design and development!

It's a little 11ty site on Netlify, where you can contribute to anytime — particularly by adding conferences that fit the vibe that you know about.

Notably, every conference listed has a permalink (example). We did that so we could play around with dynamically generating images for them. It's super basic right now, but it was fun to play with. Dynamic CMS data is fed into an SVG, then also converted to a PNG at build time. Fancy. My hope is to upgrade the CMS to allow for cool custom backgrounds for each conference and then use them in these generated graphics.

Also, each conference has a little button where you can email it to somebody via Netlify functions, like we wrote about.

Jobs are $100 off in May

You know we have a Job Board here on CSS-Tricks. It's powered by the CodePen Job Board, which also powers the ShopTalk Show Job Board.

The price of posting a job is reduced from $299 to $199 just in May and runs for 60 days instead of 30.

Post one!

Dave and I have talked with people like Heydon Pickering, Jessica Ivins, Scott Jehl, and Guillermo Rauch on ShopTalk Show.

It's a great podcast, really ;). You should subscribe.

I bought a new bike!

A Specialized Vado (eBike). Cool right?

The trip from my house to work is a short bike ride, but it's a fairly dramatic elevation change, and my big ass is not capable of hauling itself up there. It's much easier with this, even with a couple of loaded saddlebags and a toddler on the back of it.

The post CSS-Tricks Chronicle XXXV appeared first on CSS-Tricks.

The Thinking Behind Simplifying Event Handlers

Css Tricks - Thu, 05/09/2019 - 4:24am

Events are used to respond when a user clicks somewhere, focuses on a link with their keyboard, and changes the text in a form. When I first started learning JavaScript, I wrote complicated event listeners. More recently, I've learned how to reduce both the amount of code I write and the number of listeners I need.

Let’s start with a simple example: a few draggable boxes. We want to show the user which colored box they dragged.

<section> <div id="red" draggable="true"> <span>R</span> </div> <div id="yellow" draggable="true"> <span>Y</span> </div> <div id="green" draggable="true"> <span>G</span> </div> </section> <p id="dragged">Drag a box</p>

See the Pen
Dragstart events
by Tiger Oakes (@NotWoods)
on CodePen.

The intuitive way to do it

I wrote separate event listener functions for each element when I first started learning about JavaScript events. It’s a common pattern because it's the simplest way to start. We want specific behavior for each element, so we can use specific code for each.

document.querySelector('#red').addEventListener('dragstart', evt => { document.querySelector('#dragged').textContent = 'Dragged red'; }); document.querySelector('#yellow').addEventListener('dragstart', evt => { document.querySelector('#dragged').textContent = 'Dragged yellow'; }); document.querySelector('#green').addEventListener('dragstart', evt => { document.querySelector('#dragged').textContent = 'Dragged green'; }); Reducing duplicate code

The event listeners in that example are all very similar: each function displays some text. This duplicate code can be collapsed into a helper function.

function preview(color) { document.querySelector('#dragged').textContent = `Dragged ${color}`; } document .querySelector('#red') .addEventListener('dragstart', evt => preview('red')); document .querySelector('#yellow') .addEventListener('dragstart', evt => preview('yellow')); document .querySelector('#green') .addEventListener('dragstart', evt => preview('green'));

This is much cleaner, but it still requires multiple functions and event listeners.

Taking advantage of the Event object

The Event object is the key to simplifying listeners. When an event listener is called, it also sends an Event object as the first argument. This object has some data to describe the event that occurred, such as the time the event happened. To simplify our code, we can use the evt.currentTarget property where currentTarget refers to the element that the event listener is attached to. In our example, it will be one of the three colored boxes.

const preview = evt => { const color = evt.currentTarget.id; document.querySelector('#dragged').textContent = `Dragged ${color}`; }; document.querySelector('#red').addEventListener('dragstart', preview); document.querySelector('#yellow').addEventListener('dragstart', preview); document.querySelector('#green').addEventListener('dragstart', preview);

Now there is only one function instead of four. We can re-use the exact same function as an event listener and evt.currentTarget.id will have a different value depending on the element that fires the event.

Using bubbling

One final change is to reduce the number of lines in our code. Rather than attaching an event listener to each box, we can attach a single event listener to the <section> element that contains all the colored boxes.

An event starts off at the element where the event originated (one of the boxes) when it is fired. However, it won't stop there. The browser goes to each parent of that element, calling any event listeners on them This will continue until the root of the document is reached (the <body> tag in HTML). This process is called "bubbling" because the event rises through the document tree like a bubble.

Attaching an event listener to the section will cause the focus event to bubble from the colored box that was dragged up to the parent element. We can also take advantage of the evt.target property, which contains the element that fired the event (one of the boxes) rather than the element that the event listener is attached to (the <section> element).

const preview = evt => { const color = evt.target.id; document.querySelector('#dragged').textContent = `Dragged ${color}`; }; document.querySelector('section').addEventListener('dragstart', preview);

Now we’ve reduced many event listeners to just one! With more complicated code, the effect will be greater. By utilizing the Event object and bubbling, we can tame JavaScript events and simplify code for event handlers.

What about click events?

evt.target works great with events like dragstart and change, where there are only a small number of elements that can receive focus or have input changed.

However, we usually want to listen for click events so we can respond to a user clicking on a button in an application. click events fire for any element in the document, from large divs to small spans.

Let’s take our draggable color boxes and make them clickable instead.

<section> <div id="red" draggable="true"> <span>R</span> </div> <div id="yellow" draggable="true"> <span>Y</span> </div> <div id="green" draggable="true"> <span>G</span> </div> </section> <p id="clicked">Clicked a box</p> const preview = evt => { const color = evt.target.id; document.querySelector('#clicked').textContent = `Clicked ${color}`; }; document.querySelector('section').addEventListener('click', preview);

See the Pen
Click events: Not quite working
by Tiger Oakes (@NotWoods)
on CodePen.

When testing this code, notice that sometimes nothing is appended to “Clicked” instead of when clicking on a box. The reason that it doesn't work is that each box contains a <span> element that can be clicked instead of the draggable <div> element. Since the spans don’t have a set ID, the evt.target.id property is an empty string.

We only care about the colored boxes in our code. If we click somewhere inside a box, we need to find the parent box element. We can use element.closest() to find the parent closest to the clicked element.

const preview = evt => { const element = evt.target.closest('div[draggable]'); if (element != null) { const color = element.id; document.querySelector('#clicked').textContent = `Clicked ${color}`; } };

See the Pen
Click events: Using .closest
by Tiger Oakes (@NotWoods)
on CodePen.

Now we can use a single listener for click events! If element.closest() returns null, that means the user clicked somewhere outside of a colored box and we should ignore the event.

More examples

Here are some additional examples to demonstrate how to take advantage of a single event listener.

Lists

A common pattern is to have a list of items that can be interacted with, where new items are inserted dynamically with JavaScript. If we have event listeners attached to each item, then y\our code has to deal with event listeners every time a new element is generated.

<div id="buttons-container"></div> <button id="add">Add new button</button> let buttonCounter = 0; document.querySelector('#add').addEventListener('click', evt => { const newButton = document.createElement('button'); newButton.textContent = buttonCounter; // Make a new event listener every time "Add new button" is clicked newButton.addEventListener('click', evt => { // When clicked, log the clicked button's number. document.querySelector('#clicked').textContent = `Clicked button #${newButton.textContent}`; }); buttonCounter++; const container = document.querySelector('#buttons-container'); container.appendChild(newButton); });

See the Pen
Lists: no bubbling
by Tiger Oakes (@NotWoods)
on CodePen.

By taking advantage of bubbling, we can have a single event listener on the container. If we create many elements in the app, this reduces the number of listeners from n to two.

let buttonCounter = 0; const container = document.querySelector('#buttons-container'); document.querySelector('#add').addEventListener('click', evt => { const newButton = document.createElement('button'); newButton.dataset.number = buttonCounter; buttonCounter++; container.appendChild(newButton); }); container.addEventListener('click', evt => { const clickedButton = evt.target.closest('button'); if (clickedButton != null) { // When clicked, log the clicked button's number. document.querySelector('#clicked').textContent = `Clicked button #${clickedButton.dataset.number}`; } }); Forms

Perhaps there’s a form with lots of inputs, and we want to collect all the user responses into a single object.

<form> <label>Name: <input name="name" type="text"/></label> <label>Email: <input name="email" type="email"/></label> <label>Password: <input name="password" type="password"/></label> </form> <p id="preview"></p> let responses = { name: '', email: '', password: '' }; document .querySelector('input[name="name"]') .addEventListener('change', evt => { const inputElement = document.querySelector('input[name="name"]'); responses.name = inputElement.value; document.querySelector('#preview').textContent = JSON.stringify(responses); }); document .querySelector('input[name="email"]') .addEventListener('change', evt => { const inputElement = document.querySelector('input[name="email"]'); responses.email = inputElement.value; document.querySelector('#preview').textContent = JSON.stringify(responses); }); document .querySelector('input[name="password"]') .addEventListener('change', evt => { const inputElement = document.querySelector('input[name="password"]'); responses.password = inputElement.value; document.querySelector('#preview').textContent = JSON.stringify(responses); });

See the Pen
Forms: no bubbling
by Tiger Oakes (@NotWoods)
on CodePen.

Let's switch to a single listener on the parent <form> element instead.

let responses = { name: '', email: '', password: '' }; document.querySelector('form').addEventListener('change', evt => { responses[evt.target.name] = evt.target.value; document.querySelector('#preview').textContent = JSON.stringify(responses); }); Conclusion

Now we know how to take advantage of event bubbling and the event object to simplify complex jumbles of event handlers into just a few… and sometimes down to just one! Hopefully this article has helped you think about your event handlers in a new light. I know this was a revelation to me after I’d spent my early development years writing duplicative code to accomplish the same thing.

The post The Thinking Behind Simplifying Event Handlers appeared first on CSS-Tricks.

A responsive grid layout with no media queries

Css Tricks - Thu, 05/09/2019 - 4:23am

Andy Bell made a really cool demo that shows us how to create a responsive grid layout without any media queries at all. It happens to look like this when you change the size of the browser window:

I think this is a wonderful layout technique that’s just 6 lines (!) of CSS.

.auto-grid { --auto-grid-min-size: 16rem; display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--auto-grid-min-size), 1fr)); grid-gap: 1rem; }

What this shows us is that we don’t have to write a million media queries to change the number of columns in a grid. Andy also proves that CSS Grid can automate so much of the tedious work of styling layouts.

I’ve seen this technique used in a couple of places (and we have a few starter grid templates to boot) but Andy’s article about how it all works finally made it all sink in just how useful grid is.

Direct Link to ArticlePermalink

The post A responsive grid layout with no media queries appeared first on CSS-Tricks.

The Impact of Team Collaboration and Communication on Projects

Css Tricks - Thu, 05/09/2019 - 4:22am

(This is a sponsored post.)

The CSS-Tricks team was cracking up the other day when Miranda introduced us to something called "swoop and poop." That was a new term for most of us, but tell me if you've ever experienced this for yourself.

The idea is that someone in an organization — usually someone higher up on the chain, like a manager or director — has had no involvement in a project but "swoops" into a review session for it (like a team demo) and "poops" all over the work that's been done. You know, things like colors in the design, why we're using this framework versus that, or any number of various things that pay no mind to the scope of the project or the meeting. And it's not like anyone want to push back on a HiPPO.

We then all turned to Chris because, well, case in point. Just kidding!

The thing about "swoop and poop" is that it's totally avoidable. Sure, it's a funny thing to say and there's a lot of truth in it, but the issue really comes down to a lack of transparency and communication.

That's where a system like monday.com can swoop in and make things shine. It's a project management platform that's more than project management. It has all the time tracking, milestones, calendars and task lists that you might expect, but there's a lot more to help facilitate better collaboration and communication among — not just the immediate team members of a project — but everyone across the organization.

We're talking about things like shared assets, comments and chat to help everyone on the team communicate better. Even better, monday.com puts all of these things in a central place so everyone has access to it. And if you feel out of the loop on a project, simply check your personalized news feed to catch up on all the latest activity for the things that directly affect your work.

That's exactly the sort of remedy that prevents any ol' person from swooping into a meeting and dropping bombs all over the work. By capturing important details, assets, decisions, discussions, budgets and everything else you could ever need on a project, monday.com makes it tough to be out of the loop, which leads to better team collaboration and communication.

Try monday.com and experience the difference better communication makes. It's free to sign up, so go ahead and give it a spin.

Get Started

Direct Link to ArticlePermalink

The post The Impact of Team Collaboration and Communication on Projects appeared first on CSS-Tricks.

A Few Functional Uses for Intersection Observer to Know When an Element is in View

Css Tricks - Wed, 05/08/2019 - 4:46am

You might not know this, but JavaScript has stealthily accumulated quite a number of observers in recent times, and Intersection Observer is a part of that arsenal. Observers are objects that spot something in real-time — like birdwatchers going to their favorite place to sit and wait for the birds to come.

Different observers observe different things (not everyone watches hawks).

The very first observer I came to know was the Mutation Observer that looks for changes to the DOM tree. It was a one-of-a-kind at the time, but now we have many more observers.

Intersection Observer observes the "intersection" (i.e. the passing across) of an element through one of its ancestor elements or the area on screen where the page is visible (aka the viewport).

It’s sort of like watching a train pass through a station. You can see when the train comes in, when it leaves, and how long it was stationary.

Knowing when an element is about to come into view, if it has gone out of view, or how long it’s been since it came into view all have useful applications. So, we’ll see some of those use cases now — right after seeing the code for creating an IntersectionObserver object by way of the Intersection Observer API.

A quick overview of IntersectionObserver

The Intersection Observer API has already gained wide support at the time of this writing.

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

DesktopChromeOperaFirefoxIEEdgeSafari584555No1612.1Mobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox12.246No677466

But if you want to check whether Intersection Observer is supported while you’re working with it, you could see if the property IntersectionObserver exists in the window object:

if(!!window.IntersectionObserver){} /* or */ if('IntersectionObserver' in window){}

OK, now for a look at the object creation:

var observer = new IntersectionObserver(callback, options);

The IntersectionObserver object’s constructor takes two parameters. The first one is a callback function that’s executed once the observer notices an intersection and has asynchronously delivered some data about that intersection.

The second (optional) parameter is options, an object with information to define what’s going to be the "intersection." We may not want to know when an element is about to come into view, but only when it’s fully visible. Something like that is defined through the options parameter.

Options has three properties:

  • root - The ancestor element/viewport that the observed element will intersect. Think of it as the train station that the train will intersect.
  • rootMargin - A perimeter of the root element, shrinking or growing the root element’s area to watch out for intersection. It’s similar to the CSS margin property.
  • threshold - An array of values (between 0 and 1.0), each representing the distance an element has intersected into or crossed over in the root at which the callback is to be triggered.

Let’s say our threshold is 0.5. The callback is triggered when the element is in or passes its half-visible threshold. If the value is [0.3, 0.6], then the callback is triggered when the element is in or passes its 30% visible threshold and also, its 60% visible threshold.

That’s enough of the theory now. Let’s see some demos. First up, lazy loading.

Use Case 1: Lazy loading images

See the Pen
Intersection Observer - Lazy Load
by Preethi Sam (@rpsthecoder)
on CodePen.

To see the loading at the mark, view this webpage since the embedded demo doesn't show that.

CSS-Tricks has thoroughly covered lazy loading in before and it’s typically done like this: display a lightweight placeholder where images are intended, then swap them out for the intended images as they come (or are about to come) into view. Believe me, there’s nothing lazy about implementing this — that is, until we get something native to work with.

We’ll apply the same mechanics. First, we’ve a bunch of images and have defined a placeholder image to display initially. We’re using a data attribute carrying the URL of the original image to be shown that defines the actual image to load when it comes into view.

<img src="placeholder.png" data-src="img-1.jpg"> <img src="placeholder.png" data-src="img-2.jpg"> <img src="placeholder.png" data-src="img-3.jpg"> <!-- more images -->

The rest is scripting.

let observer = new IntersectionObserver( (entries, observer) => { entries.forEach(entry => { /* Here's where we deal with every intersection */ }); }, {rootMargin: "0px 0px -200px 0px"});

The callback function above is an arrow function (though you can use a normal function instead).

The callback function receives two parameters: a set of entries carrying the information about each intersection and the observer itself. Those entries can be filtered or looped through so we can then deal with the intersection entries that we want. As for the options, I’ve only provided the rootMargin value, letting the root and threshold properties fall into their default values.

The root default is the viewport and threshold default is 0 — which can be roughly translated to "ping me the very moment that the element appears in the viewport!"

The oddity, though, is that I reduced the viewport’s observation area by two hundred pixels at the bottom using rootMargin. We wouldn’t typically do this for lazy loading. Instead, we might increase the margin or let it default. But reducing isn’t something we would usually do in this situation. I did it only because I want to demonstrate the original images loading at the threshold in the observed area. Otherwise, all the action would happen out of view.

When the image intersects the viewport’s observer area (which is 200px above the bottom in the demo), we replace the placeholder image with the actual image.

let observer = new IntersectionObserver( (entries, observer) => { entries.forEach(entry => { /* Placeholder replacement */ entry.target.src = entry.target.dataset.src; observer.unobserve(entry.target); }); }, {rootMargin: "0px 0px -200px 0px"});

entry.target is the element observed by the observer. In our case, those are the image elements. Once the placeholder is replaced in an image element, we don’t have to observe it anymore, so we call the observer’s unobserve method for it.

Now that the observer is ready, it’s time to start observing all the images by using its observer method:

document.querySelectorAll('img').forEach(img => { observer.observe(img) });

That’s it! we’ve lazy loaded the images. Onto the next demo.

Use Case 2: Auto-pause video when it’s out of view

Let’s say we’re watching a video on YouTube and (for whatever reason) we want to scroll down to read the comments. I don’t know about you, but I don’t usually pause the video first before doing that, which means I miss some of the video while I’m browsing.

Wouldn’t it be nice if the video paused for us when we scroll away from it? It would be even nicer if the video resumed when it’s back in view so there’s no need to hit Play or Pause at all.

Intersection Observer can certainly do that.

See the Pen
IntersectionObserver: auto-pause out of view video
by Preethi Sam (@rpsthecoder)
on CodePen.

Here’s our video in the HTML:

<video src="OSRO-animation.mp4" controls=""></video>

Here’s how we toggle between play and pause:

let video = document.querySelector('video'); let isPaused = false; /* Flag for auto-paused video */ let observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if(entry.intersectionRatio!=1 && !video.paused){ video.pause(); isPaused = true; } else if(isPaused) {video.play(); isPaused=false} }); }, {threshold: 1}); observer.observe(video);

Before I show you how we’re pausing and playing the video during each intersection (i.e. entry), I want to bring your attention to the threshold property of the options.

Th threshold has a value of 1. Both root and rootMargin will default. This is the same as saying, "hey, let me know as soon the element is fully visible on the viewport."

Once the intersection happens and the callback is triggered, we pause or play the video based on this logic:

I have not called unobserve for the video, so the observer keeps observing the video and pauses every time it goes out of view.

Use Case 3: See how much content is viewed

This can be interpreted and implemented in many ways depending on what your content is and the way you prefer to measure how much of it has been viewed.

For a simple example, we’ll observe the last paragraph of every article in a list of articles on a page. Once an article’s last paragraph becomes fully visible, we will consider that article read — like how we might say that seeing the last coach of a train counts as having seen the whole train.

Here’s a demo that shows two articles on a page, each containing a number of paragraphs.

See the Pen
IntersectionObsever: content viewed
by Preethi Sam (@rpsthecoder)
on CodePen.

Our simplified HTML is something like this:

<div id="count"><!-- The place where "number of articles viewed" is displayed --></div> <h2>Article 1</h2> <article> <p><!-- Content --></p> <!-- More paragraphs --> </article> <h2>Article 2</h2> <article> <p><!-- Content --></p> <!-- More paragraphs --> </article> <!-- And so on... --> let n=0; /* Total number of articles viewed */ let count = document.querySelector('#count'); let observer = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if(entry.isIntersecting){ count.textContent= `articles fully viewed - ${++n}`; observer.unobserve(entry.target); } }); }, {threshold: 1}); document.querySelectorAll('article > p:last-child').forEach(p => { observer.observe(p) });

During each intersection — the full view of the last paragraph of an article — we’re incrementing a count: n, that represents the total number of articles read. Then we display that number above the list of articles.

Once we’ve counted in an intersection of the last paragraph, it doesn’t need to be observed anymore, so we call unobserve for it.

Thanks for observing along!

That’s it for the examples we’re going to look at together for this post. You probably get the idea of how using it is, to be able to observe elements and trigger events based on where they intersect the viewport.

That said, it’s worth using caution when making visual changes based on the intersection data obtained through the observer. Sure, Intersection Observer is hassle free when it comes to logging intersection data. But when it’s being used to make onscreen changes, we need to ensure the changes aren’t lagging, which is a possibility because we’re basically making changes based on data retrieved asynchronously. That might require a little bit of time to load.

As we saw, each intersection entry has a set of properties conveying information about the intersection. I didn’t cover all of them in this post, so be sure to review them.

The post A Few Functional Uses for Intersection Observer to Know When an Element is in View appeared first on CSS-Tricks.

Getting To Know The MutationObserver API

Css Tricks - Wed, 05/08/2019 - 4:45am

MutationObserver watches the DOM, specifically the places you tell it to, like:

document.querySelector('#watch-this');

...and it can tell you (trigger a callback) when stuff happens — like when a child is added, removed, changed, or a number of other things.

I used it just the other day to watch the <head> of a Pen and detected newly-injected processed Sass code, so you could use CodePen to see Sass and CSS side by side:

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

Direct Link to ArticlePermalink

The post Getting To Know The MutationObserver API appeared first on CSS-Tricks.

Why, How, and When to Use Semantic HTML and ARIA

Css Tricks - Tue, 05/07/2019 - 4:22am

Semantic HTML and Accessible Rich Internet Applications (ARIA) help create interfaces that work for everyone in the most performant, robust, and simple way possible. They add essential meaning to your content, which lets web browsers, search engines, screen readers, RSS readers, and ultimately users understand it.

And yet, many people still don’t use them. I wanted to know why, so I set up a Twitter poll. The most common reason people gave was a lack of awareness and understanding of the benefits of using semantic HTML and ARIA.

Let’s look over the benefits of using HTML and ARIA, why starting with semantic HTML is the way to go, and why ARIA ought to come in as a last resort.

Starting with raw text

The <body> element of an HTML document contains the main content a user sees on a page. If content is put inside the body without any additional elements, the browser has no way of differentiating between different types of content, like paragraphs and headings.

<body> A Study of Butterflies Butterflies are little bugs with cute wings. Butterfly Habitats Butterflies live in flower houses and hang out at dank coffeeshops. </body>

If the browser can’t differentiate between pieces of content, then it can’t present that content to the user in a meaningful way. That means:

  • We can’t style the headings differently from paragraphs.
  • It’s harder for search engines to interpret the content, meaning it’s likely to rank poorly and be difficult for users to find.
  • Screen readers and other assistive technology can’t communicate it properly to the user.

Not to mention, it’s more than a bit awkward visually:

Adding some structure with HTML

To provide some structure we could wrap the lines of text here in divs like this:

<div>A Study of Butterflies.</div> <div>Butterflies are little bugs with cute wings.</div> <div>Butterfly Habitats</div> <div>Butterflies live in flower houses and hang out at dank coffeeshops.</div>

This is slightly better because each piece of content is displayed in the browser on its own line instead of one long unbroken line of text.

But there’s still a distinct lack of meaning.

Which are headings and which are paragraphs? It’s hard to tell, and impossible for assistive technology to determine. That’s because the headings and paragraphs are wrapped in divs which are meaningless on their own. In this example, browsers, CSS, search engines and screen readers are still none the wiser.

Communicating meaning with styles

We could add styling to the divs because they can be targetted with CSS. This lets us improve the visual appearance to provide meaning, context, and hierarchy.

See the Pen
Non-Semantic HTML Demo
by Geoff Graham (@geoffgraham)
on CodePen.

Here the CSS targets the first and third divs to apply heading styles. This isn't maintainable because another paragraph added afterward, for example, would get styled as a heading.

We could give each div a unique attribute such as an ID or class name, to give us more styling control, like this:

<div class="heading1">A Study of Butterflies</div> <div class="paragraph">Butterflies are little bugs with cute wings.</div> <div class="heading2">Butterfly Habitats</div> <div class="paragraph">Butterflies live in flower houses and hang out at dank coffeeshops.</div>

I explain why you should use classes instead of IDs for styling in my online book, MaintainableCSS.

Now we can target the different elements with CSS like this:

.heading1 { /* styles here */ } .paragraph { /* styles here */ } .heading2 { /* styles here */ }

While this approach is a little better, it only communicates meaning for sighted users. It doesn't provide meaning to search engines, RSS readers and screen readers. In other words, it’s not semantic and not very accessible as a result.

Introducing semantic HTML

HTML provides many elements that are designed to give meaning to content, including elements for headings and paragraphs. So, instead of relying on divs with classes named by the developer, we can use predefined HTML elements instead.

<h1>A Study of Butterflies</h1> <p>Butterflies are little bugs with cute wings.</p> <h2>Butterfly Habitats</h2> <p>Butterflies live in flower houses and hang out at dank coffeeshops.</p>

Much better! With semantic HTML like this, the content will inherit default styles from the browser (aka User Agent). We can even use other semantic HTML elements, like <b> which tells the browser to “bring to attention" by making text bold.

Crucially, using semantic HTML also means:

  • We can use CSS to add our own styling.
  • Search engines can index the content so that it ranks well enough that users can find it.
  • RSS readers can parse and style the elements appropriately.
  • Screen readers and other assistive technologies can communicate elements properly to the user.

While it’s not massively important in these short examples, the code is also more concise which makes a big difference when considering an entire site.

Semantic HTML is standards-based and stable. This means any HTML processor in the future will be able to understand it and present it correctly to users. It will also help subsequent code authors if they need to make changes.

Additional benefits of semantic HTML

In addition to the benefits we’ve covered so far, some browsers add useful enhancements to semantic HTML for free.

For example, using the HTML telephone input (<input type="tel">) will give users a telephone-specific keypad on some mobile browsers.

Identifying a form input as a telephone field will produce a telephone-specific keypad in iOS. Careful though, because it’s just for telephone numbers and not meant for any number, like credit cards.

Other browsers give users the option to switch to a simplified view of the page, like Safari’s Reader Mode. Without semantic HTML, Reader Mode would produce something much like the one-line string of text we started with. But, by using semantic HTML, we get a clean reading experience without any additional styling on our end:

The About page on my personal website viewed with Safari’s Reader Mode, comparing unsemantic HTML (left) with semantic HTML (right).

You can read more about this in Mandy Michael’s article on building websites for Safari Reader Mode and other reading apps.

When ARIA makes things better

Like semantic HTML, ARIA is a W3 standard that helps make interfaces more accessible to people who use screen readers and other assistive technologies to consume content.

Error messages are a good example. If a user leaves a required form field blank, the HTML for the error might look like this:

<label for="first-name">First name</label> <span>Enter your first name</span> <input type="text" name="first-name" id="first-name">

A sighted user will be able to see the error above the field. But when a screen reader focuses on the input, the error won’t be announced because the error message isn’t linked to the input.

ARIA can be used to associate the error with the input like this:

<label for="first-name">First name</label> <span id="first-name-error">Enter your first name</span> <input type="text" name="first-name" id="first-name" aria-describedby="first-name-error">

Now the error message is announced when the input is in focus.

Using ARIA and JavaScript together

ARIA is most useful when JavaScript is involved. JavaScript is usually required to create more complex and dynamic interactions like hiding, showing and changing elements without a page refresh. Think toggle menus, accordions, tabs, auto-completes, sortable tables, loading content and saving, sending or getting data. Enhancing interfaces like this often breaks the experience for screen reader users.

Take a button that, when selected, reveals other content. In the original state, a sighted user will initially see a button and no content and, when the button is clicked, the content appears.

A visually-impaired user with a screen reader, however, usually relies on spoken cues as they navigate through an interface. But when a screen reader focuses on the button, there’s nothing to tell it if the content is currently in view and needs to be read.

The aria-expanded attribute can be added to the button, and JavaScript can toggle its value between true (content is showing) and false (content is hidden). This helps to meet Inclusive Design Principle #1, provide a comparable experience to screen reader users.

<button aria-expanded="false">Toggle content</button> <div hidden>Some content</div> Try to avoid using ARIA to fix unsemantic HTML

ARIA attributes can be used to make unsemantic HTML more accessible to screen reader users. For example, a developer who is struggling to style a native checkbox across multiple browsers might decide to use a div and some JavaScript to emulate one.

We can add a role of checkbox to make the div identity itself as a checkbox to screen reader users:

<div role="checkbox"></div>

We must also use the aria-checked attribute to indicate whether or not the checkbox is checked like this:

<div role="checkbox" aria-checked="false"></div>

But, this still isn’t enough to make it behave like a checkbox because divs aren’t focusable by keyboards like <input type="checkbox"> is. We could make them focusable by adding tabindex="0":

<div role="checkbox" aria-checked="false" tabindex="0"></div>

But even then, a real checkbox, when submitted as part of a form, will send its value. Because this isn’t an actual a checkbox, it won’t submit its value without using JavaScript.

And if that weren’t enough already, users can check or un-check a real checkbox by pressing the Space key. And, the form the checkbox belongs to can be submitted by pressing Enter when the checkbox is in focus. But the div-version checkbox won’t do this without even more JavaScript.

Not only is this more work and more code, but the approach only actually works for people who use technology that understands these particular ARIA attributes. That’s a lot of effort, a lot of code and a lot of problems that we can avoid entirely if we just use semantic HTML:

<input type="checkbox">

There’s no denying that ARIA is useful in certain situations, but starting with semantic, accessible HTML where possible is infinitely simpler and more reliable. That’s why the first rule of ARIA is not to use it.

Conclusion

Inclusive design is about providing the best possible experience to the broadest range of users. Semantic HTML helps technologies and therefore users understand content on the web. Enhancements offered by some browsers and devices mean that users get an even better experience baked in.

And when semantic HTML alone is not enough on its own, ARIA can provide more context for users of assistive technologies, but use it with caution. It's not a hard and fast cure for unsemantic markup and can become complicated, as we saw in that last example.

In short, do the hard work to make things inclusive. It’s a win for you and a win for the web.

The post Why, How, and When to Use Semantic HTML and ARIA appeared first on CSS-Tricks.

The Place of UX

Css Tricks - Tue, 05/07/2019 - 4:21am

Every time "UX" comes out of my mouth or is typed by my fingers, I think, "did I just use that term correctly?" It feels like such a big and loaded term these days, that perhaps the way I use it only contributes to the confusion. Ryan Singer frames that problem well:

Debates continue to rage about the role of UX designers, user research, and how far knowledge about the user should permeate the organization. On one extreme, UX is seen as a specialized pocket of knowledge that informs the definition of projects and sets requirements. On the other, UX is something for which the entire organization should somehow feel responsible.

It can feel so big, like UX is literally the only thing that matters in an entire project. It can also feel so small, like 2px of extra padding on a specific dropdown will make the options easier to tap.

Direct Link to ArticlePermalink

The post The Place of UX appeared first on CSS-Tricks.

A CSS Golfing Exercise

Css Tricks - Mon, 05/06/2019 - 4:32am

Code golfing is a type of programming where the goal is to accomplish a task using as few bytes as possible. CSSBattle is a code golfing battleground where players complete to recreate target images using CSS and HTML.

The rules are fairly simple:

  • No external resources (sorry, no <img src="the-solution.png">)
  • Your solution must render correctly in Chrome (just for scoring purposes)

This can be a pretty fun departure from day-to-day front-end work. There’s no need to worry about maintainability, semantics, performance, accessibility, or anything other than making a thing really, really small and still render correctly.

A golf solution in 12 attempts

This type of thinking is a pretty dramatic departure from how most of us are writing front-end code for production sites (I hope!), so I’ve been posting all of my solutions on GitHub in an effort to both share some knowledge and learn from others. As a fortunate side effect, it also means there’s a fairly detailed history of my submissions.

Here’s a start-to-finish account of my attempts CSSBattle’s 7th target, which looks like this:

CSSBattle Target #7 — Leafy Trail The "just center the dang thing" method

A reasonable first approach is to simply stick an element in the middle of the page, slap a box shadow and a border radius on it, and call it done. If we were writing this "for real," it might look like this:

<!DOCTYPE html> <html> <head> <style> body { background: #0B2429; margin: 0; } .leaf { width: 150px; height: 150px; border-radius: 67% 0; background: #F3AC3C; margin: 75px 0 75px 175px; box-shadow: -50px 0 #998235, -100px 0 #1A4341 } </style> </head> <body> <div class="leaf"/> </body> </html>

But that’s 423 bytes! That won’t do for CSS golf, so let’s see what we can remove.

Attempt 1: 144 bytes <p style="margin:75 167;height:150;width:150;border-radius:67%0;box-shadow:-50px 0#998235,-100px 0#1A4341,0 0 0 5in #0B2429;background:#F3AC3C">

Here’s a golfed version. There’s definitely some weirdness going on here — no <!DOCTYPE>, no <html>, no <body>, no nothin’. The browser doesn’t need them (and, in fact, inserts them for us), so we save a lot of bytes by leaving them out. We’re using <p> instead of <div> since it’s shorter, and we don’t close the tag at all since it’s not required for things to render.

The CSS itself isn’t much different, aside from the fact that we’ve used a huge box shadow instead of a background on the body element ("background" is long so avoiding it can be beneficial). It’s also inlined in the element since a <style></style> tag costs extra bytes.

You may have noticed that we used 5in for the spread in our last box shadow. Playing with weird units is a huge part of CSS golfing. In this case, we just need the shadow to cover the 400x300 canvas and ‘5in' (480px) is shorter than any pixel value.

Attempt 2: 141 bytes <p style=margin:75+167;height:150;width:150;border-radius:67%0;box-shadow:-50px+0#998235,-100px+0#1A4341,0+0+0+5in#0B2429;background:#F3AC3C>

This introduces a pretty important golfing trick: replacing spaces with plus signs allows us to remove the quotes around attributes, saving a couple bytes. I’m not totally sure why this works. Someone suggested it may be related to this part of the HTML spec. If you have a better answer, please let me know!

This attempt also cleans up a couple of whitespace mistakes from the last attempt.

Attempt 3: 126 bytes <body bgcolor=F3AC3C style=margin:75+75+75+175;border-radius:67%+0;box-shadow:-50px+0#998235,-100px+0#1A4341,0+0+0+5in#0B2429>

Using a <body> tag instead of a <p> means that:

  • We no longer spend bytes setting height or width on a paragraph
  • We get access to bgcolor

bgcolor is a deprecated attribute that comes up often in CSS golf solutions. It only works on a few tags (<body> included), and does two great things:

  • Saves us from spending bytes on "background:"
  • Saves us a byte by allowing us to omit # in hex colors. Additionally, if a color ends in one or two zeros, we can remove them and it will still render correctly. For example, FFFF00 is the same as FFFF.

There’s a golf regression in this iteration! Can you spot it?

The "border" method

By this point, I had spent quite a few hours tinkering on and off with this target and was getting pretty stuck. Fortunately, CSSBattle has a friendly community on Spectrum that is more than willing to lend a hand.

At the time, Praveen held the #1 spot with two bytes fewer than I had managed, so I asked for some help. He suggested leveraging both the <body> and <html> elements to position everything while using borders in place of a background color.

Attempt 4: 126 bytes <style>*{border-radius:67%+0;border:75px solid#F3AC3C;margin:0 50;box-shadow:-50px 0#998235,-100px 0#1A4341,0 0 0 5in#0B2429

This is a pretty huge departure from our last strategy. Our body tag is gone and we’re using <style>*{ to target the <html> and <body> tags that the browser inserts for us. The combination of margin and border nudges our shape exactly where it needs to be, and the box-shadow on <body> covers all the excess stuff you’d see from styling on <html>.

This was tough for me to grok, but Praveen made a diagram that explains things pretty well. Here’s a prettied up version:

Margins and borders on <html> and <body>

a and b are the margin and border on <html>, and c is the margin on <body>. The right margin on <body> doesn’t do anything since there’s no room to push the <body> to the left and it already has zero width.

Once our box shadows are applied, b is covered up and all that’s left is our target image.

There are still some optimizations missing here though. Dorus van den Oord was able to take the border method down to a lean 121 bytes, offering this cryptic bit of advice:

small hint for getting to that 121: What if you could move an element by a quarter of a ...?

Attempts 5 and 6: 122 bytes <style>*{border-radius:67%+0;border:75px solid#F3AC3C;margin:0 50;box-shadow:-53q 0#998235,-25vw 0#1A4341,0 0 0 5in#0B2429

Turns out all we needed was a unit hardly anyone’s ever heard of (q) (and the humble vw). Having to write "px" is rarely correct in CSS golf, so it’s something to be on the lookout for. Here, we can replace 100px with 25vw and 50px with 53q.

A q, or quarter-millimeter, is exactly that — 1/4th of a millimeter, or just under a pixel. The q unit is a staple of CSS golf as one of two values (the other being %) that require just one byte to express. I’ve combined my 5th and 6th attempts here since both were just unit tweaks. We’re still a byte off from 121 though!

Attempt 7: 121 bytes <style>*{border-radius:67%0;border:75px solid#F3AC3C;margin:0 50;box-shadow:-53q 0#998235,-25vw 0#1A4341,0 0 0 5in#0B2429

We finally fixed that regression from the third attempt, thanks to a pull request from Praveen. A percentage doesn’t need a space between it and subsequent values, so we can save a byte in our border-radius. This is a great example of how sharing code can help everyone involved. I had been stuck on this for a pretty dang long time.

The "funky margin" method

Borders aren’t the only approach, though! Enter Rasmus Fløe’s funky margin:

I got 123 chars on #7 by using box-shadow and a funky margin:75 400 75-150 :)

Attempt 8: 120 bytes <body bgcolor=0B2429 style=border-radius:67%0;margin:75+400+75-150;box-shadow:86mm+0#F3AC3C,73mm+0#998235,75vh+0#1A4341>

Here’s how this works, as Rasmus explains it:

positive right margin pushes it off canvas to the left — and negative left margin stretches the element to the wanted width :)

Here it is drawn out:

The Rasmus Fløe "funky margin" method

The right margin (b) pushes the <body> element all the way to the left, collapsing it to zero width. The negative left margin (a) then stretches it back to 150px wide (the width of the leaf shape), and then our box shadow (c) is offset enough to be in view. This is awesome because we no longer have to deal with negative box shadows in order to get everything to layer correctly.

We’re also back to bgcolor and get to leverage a nice quirk of background colors: because <html> doesn’t have its own background color, it inherits one from <body>.

Attempts 9 and 10: 118 bytes <body bgcolor=0B2429 style=border-radius:67%0;margin:75+340+75-90;box-shadow:7cm+0#F3AC3C,57mm+0#998235,55vh+0#1A4341>

With a bit more unit-wrangling we’re able to save ourselves two more bytes (props to Dorus, who was the first to discover this optimization). Adjusting the margins saves a digit (150 becomes 90), and, as a sweet bonus, we get to convert 86mm to 70mm, which becomes 7cm. I’ve again combined two attempts here which were minor unit fixes. (I’m embarrassed to say I initially missed the mm-cm conversion.)

Attempt 11: 117 bytes <body bgcolor=0B2429 style=border-radius:67%0;margin:75+85%75-90;box-shadow:7cm+0#F3AC3C,57mm+0#998235,55vh+0#1A4341>

Romain Deltour was the first to find this 117-byte solution. Changing 340 to 85% means we get to omit a space after one of our values (just like we did with border-radius), saving another byte.

Attempt 12: 115 bytes <body bgcolor=0B2429 style=border-radius:67%0;margin:75+85%75-90;box-shadow:7cm+0#F3AC3C,57mm+0#998235,55vh+0#7fd2>

Two full weeks after Romain’s 117-byte solution, Viacheslav Popov was able to alpha composite his way to 115 bytes via 4-digit hex codes.

I really love this because — not only is it dang clever — but a lot of people (myself included) thought the target had already been fully optimized. Viacheslav’s persistence both sparked a new round of discussion and added another CSS-Trick™ to our arsenal for future targets.

Attempt 13: <115 bytes?

This seems awfully close to optimal to me but that certainly doesn’t mean it can’t be beat — why not give it a shot? There's prior art to get you started, plenty of folks willing to help, and even some tooling. Happy golfing ⛳️

The post A CSS Golfing Exercise appeared first on CSS-Tricks.

A Conspiracy to Kill IE6

Css Tricks - Mon, 05/06/2019 - 4:22am

Chris Zacharias published a few notes about why the team at YouTube added a banner that asked users to switch from IE6 to a more modern browser back in 2009:

The bittersweet consequence of YouTube’s incredible growth is that so many stories will be lost underneath all of the layers of new paint. This is why I wanted to tell the story of how, ten years ago, a small team of web developers conspired to kill IE6 from inside YouTube and got away with it.

I do not recall the exact triggering event that led to our web development team laying out plans to kill IE6 over lunch in the YouTube cafeteria. Perhaps it was the time I pushed out a CSS stylesheet that included an attribute selector on a semi-supported HTML element. Any reasonable web developer would expect this to be ignored by browsers not up to the task. This was not the case with older flavors of IE. Under very specific conditions, an attribute selector on an unsupported HTML element in IE would create an internal recursion that would at best, cause the browser to crash and at worst, trigger a blue screen of death.

There are a lot of interesting things to consider here. IE6 was notoriously difficult for developers to work with and would cause teams to spend a great deal of time fixing game-breaking bugs for what often represented a mere slither of their overall site traffic. However, it’s important to note that as soon as you make a call like this, where do you stop? It suddenly becomes easier to make a Chrome-only website, to ignore basic accessibility principles, to ignore semantic markup, and to make a website optimized for yourself. That leads us to more sticky topics, such as browser diversity and proprietary resources that seem at odds with an open, inclusive web.

I’m reminded here of Jeremy Keith’s book, Resilient Web Design, where he writes:

If a website is built using progressive enhancement then it’s okay if a particular feature isn’t supported or fails to load: Ajax, geolocation, whatever. As long as the core functionality is still available, web designers don’t need to bend over backwards trying to crowbar support for newer features into older browsers.

And Jeremy quotes Mat Marquis, who happened to work on the responsive redesign of The Boston Globe, where he argued that:

Lots of cool features on the Boston Globe don’t work when JS breaks; “reading the news” is not one of them.

Maybe there’s a middle ground here; maybe there’s not. But I find Mat and Jeremy’s approach to be more inspiring and kinder to the overall health of the web.

Direct Link to ArticlePermalink

The post A Conspiracy to Kill IE6 appeared first on CSS-Tricks.

Making the Move from jQuery to Vue

Css Tricks - Fri, 05/03/2019 - 4:27am

As someone who has used jQuery for many. years and has recently become a Vue convert, I thought it would be an interesting topic to discuss the migration process of working with one to the other.

Before I begin though, I want to ensure one thing is crystal clear. I am not, in any way whatsoever, telling anyone to stop using jQuery. That's been pretty fashionable lately, and heck, I wrote up something similar myself a few year ago ("How I'm (Not) Using jQuery"). If you get things done with jQuery and your end users are successfully using your site, then more power to you. Keep using what works for you.

This guide is more for people who may be coming from years of jQuery experience and want to see how things can be done with Vue. With that in mind, I'm going to focus on what I consider "core" jQuery use cases. I won't cover every single possible feature but instead take a "I often did [X] with jQuery" approach that may be more relatable to people considering learning Vue. (As an aside, also note that how I write my examples are simply one way of performing a task. Both jQuery and Vue give provide multiple ways to accomplish the same goal and that's a great thing!)

With that in mind, let's consider some high level things we might turn to jQuery for:

  • Finding something in the DOM (with the idea of doing something with it later)
  • Changing something in the DOM (e.g. the text of a paragraph or the class of a button)
  • Reading and setting form values
  • Form validation (which is really just a combination of the items above)
  • Ajax calls and handling the results
  • Event handling (e.g. on button click, do something)
  • Measuring or changing the styles of an element

There's more to jQuery, of course, but these uses (at least in my opinion), cover the most common use cases. Also note there's a lot of cross pollination in the list above. So, should we start with a simple one-to-one comparison of each? Nope, not so fast. Let's begin by covering the major difference in Vue applications.

Defining where Vue "works"

When we drop jQuery onto a page, we are basically adding a Swiss Army knife to JavaScript code to handle common web development tasks. We can do any of the uses case we’re going to cover in whatever order we see fit. For example, a client may ask for form validation today, then in a month or so, ask to do an Ajax-based search form in the header of the site.

Vue has one significant difference in that respect. When starting a with Vue project, we start by defining an "area" in the DOM we want it to focus on. So, let’s consider a simple prototype web page:

<body> <header> Fancy header stuff here </header> <div id="sidebar"> Some sidebar doohicky here </div> <main> <p> Main site content here, super important stuff... </p> <div id="loginForm"> A login form of course </div> </main> </body>

In a typical jQuery application, we may write code to work with the header, sidebar, and login form or something. No big whoop:

$(document).ready(function() { $('header') // something... $('#sidebar') // something... $('#loginForm') // something... });

In a Vue application, we first specify what are we're working with. Imagine our client first asked to add validation to the loginForm element. Our Vue code would specify that:

new Vue({ el: '#loginForm', // Code here... });

This means that we’d typically end up adding a second Vue application if the client later decides to have us add something to the sidebar:

new Vue({ el:'#loginForm', // Code here... }); new Vue({ el:'#sideBar', // Code here... });

Is that a bad thing? Absolutely not. Right away, we get the benefit of encapsulation. If we accidentally use a variable with a generic name (we've all done that), we don't have to worry about conflicts with other parts of your code. Later on when the client adds yet another request, having our unique, logical sets of Vue code separated out like this gives us some great peace of mind that things won't step on each other.

So, yes, a good thing. But it absolutely caused me to stop a bit when I first began using Vue. Now, onto our use cases.

Finding Stuff in the DOM

Another aspect you'll find interesting, or scary, is how to "find stuff in the DOM." That's a bit vague, but let's consider a firm example. We have a button, and when it’s clicked, we make something happen. Here's an abbreviated example of how this could look:

<button id="myButton">Click Me!</button> <!-- More stuff... --> <script> $(document).ready(function() { $('#myButton').click(function() { alert(1); }); }); </script>

Now let's compare that to how it can be done with Vue:

<div id="app"> <button v-on:click="doSomething">Click Me!</button> </div> <script> const app = new Vue({ el:'#app', methods: { doSomething: function() { alert(1); } } }); </script>

The Vue application is a bit more verbose, but note how the markup has a direct connection between the action ("click") and the function that will be called. Vue's code doesn't have a tie back to the DOM (outside of the el portion where we define where it needs to work). This was easily one of the things that sold me on Vue the most — it feels easier to tell what is going on. Also, I didn't need to worry so much about the ID value and selectors. If I change the class or ID of the button, I don't need to go back into my code and worry about updating selectors.

Let's consider another example: finding and changing text in the DOM. Imagine that button, on click, now changes the text of another part of the DOM.

<button id="myButton">Click Me!</button> <span id="result"></span> <!-- More stuff... --> <script> $(document).ready(function() { $('#myButton').click(function() { $('#result').text('You clicked me, thanks!'); }); }); </script>

I've added a new span and now, when the button is clicked, we use another selector to find it and use a jQuery utility method to change the text inside it. Now consider the Vue version:

<div id="app"> <button v-on:click="doSomething">Click Me!</button> <!-- On click, change text in this span --> <span>{{resultText}}</span> </div> <script> const app = new Vue({ el: '#app', data: { resultText: '' }, methods: { doSomething: function() { this.resultText = 'You clicked me, thanks!'; } } }); </script>

In this example, we're using Vue's template language (the highlighted line) to specify that we want to render a variable inside the span, which is resultText in this case. Now, when the button is clicked, we change that value and the span's inner text will change automatically.

As an aside, Vue supports a shorthand for the v-on attribute, so the button in the example could have been written with @click="doSomething" instead.

Reading and writing form variables

Working with forms is probably one of the most common — and useful — things that we can do with JavaScript. Even before JavaScript, most of my early "web development" was writing Perl script to handle form submissions. As the primary way of accepting user input, forms have always been critical to the web and that's probably going to stay the same for quite some time. Let's consider a simple jQuery example of reading a few form fields and setting another:

<form> <input type="number" id="first"> + <input type="number" id="second"> = <input type="number" id="sum"> <button id="sumButton">Sum</button> </form> <script> $(document).ready(function() { let $first = $('#first'); let $second = $('#second'); let $sum = $('#sum'); let $button = $('#sumButton'); $button.on('click', function(e) { e.preventDefault(); let total = parseInt($first.val(),10) + parseInt($second.val(),10); $sum.val(total); }); }); </script>

This code demonstrates how jQuery can both read and write via the val() method. We end up getting four items from the DOM (all three form fields and the button) and use simple math to generate a result. Now consider the Vue version:

<form id="myForm"> <input type="number" v-model.number="first"> + <input type="number" v-model.number="second"> = <input type="number" v-model="sum"> <button @click.prevent="doSum">Sum</button> </form> <script> new Vue({ el: '#myForm', data: { first: 0, second: 0, sum: 0 }, methods: { doSum: function() { this.sum = this.first + this.second; } } }) </script>

This introduces some interesting Vue shortcuts. First, v-model is how Vue creates two way data binding between values in the DOM and in JavaScript. The data block variables will automatically sync up with the form fields. Change the data, and the form updates. Change the form, and the data updates. The .number is a flag to Vue to treat the inherit string values of form fields as numbers. If we leave this off and do addition as we are, we'll see string additions and not arithmetic. I've been working with JavaScript for nearly a century and still screw this up.

Another neat "trick" is @click.prevent. First, @click defines a click handler for the button, then the .prevent portion blocks the browser’s default behavior of submitting the form (the equivalent of event.preventDefault()).

The final bit is the addition of the doSum method that's bound to that button. Note that it simply works with the data variables (which Vue makes available in the this scope).

While this is mostly my personal feeling here, I really love the lack of query selectors in the script when writing in Vue and how the HTML is much more clear about what it's doing.

Finally, we could even get rid of the button completely:

<form id="myForm"> <input type="number" v-model.number="first"> + <input type="number" v-model.number="second"> = <input type="number" v-model="sum"> </form> <script> new Vue({ el: '#myForm', data: { first: 0, second: 0 }, computed: { sum: function() { return this.first + this.second; } } }) </script>

One of the cooler features of Vue is computed properties. They are virtual values that recognize when their derived values are updated. In the code above, as soon as any of the two form fields change, the sum will update. This works outside of form fields too. We could render the sum like so:

The total is {{sum}}. Working with Ajax

It’s commendable how easy jQuery has made it to use Ajax. In fact, I can say I've done Ajax "the vanilla" way probably a grand total of one time. (If you're curious, you can take a look at the spec for XMLHttpRequest and probably be happy you avoided it yourself.) jQuery's simple $.get(...) method worked in a large number of cases and when it’s needed for something more complex, $.ajax() made it easy as well. Another thing jQuery did well is the way it handles JSONP requests. While mostly unnecessary now with CORS, JSONP was a way to handle making requests to APIs on different domains.

So, what does Vue do for you to make Ajax easier? Nothing!

OK, that sounds scary but it really isn't. There are many options out there for working with HTTP requests, and Vue.js took a more agnostic route of letting us, the developers, decide how we want to handle it. So yes, that does mean a bit more work, but we've got some great options.

The first one to consider is Axios, this is a Promise-based library that is very popular among the Vue community. Here's a simple example of it in action (taken from their README file):

axios.get('/user?ID=12345') .then(function (response) { // handle success console.log(response); }) .catch(function (error) { // handle error console.log(error); }) .then(function () { // always executed });

Axios supports POST requests, of course, and lets us specify headers among many other options.

While Axios is very popular among Vue developers, it isn't something that really clicked with me. (At least not yet.) Instead, I've been much more a fan of Fetch. Fetch is not an external library but is a web standard way of performing HTTP requests. Fetch has very good support at roughly 90% of browsers, though that means it isn't completely safe to use, but we can always use a polyfill we need to.

While it's totally out of the scope of what we're discussing here, Kingsley Silas has written an excellent guide on using both Axios and Fetch with React.

Like Axios, Fetch is Promise-based and has a friendly API:

fetch('http://example.com/movies.json') .then(function(response) { return response.json(); }) .then(function(myJson) { console.log(JSON.stringify(myJson)); });

Both Axios and Fetch cover all types of HTTP requests, so either will fit an any number of needs. Let's look at a simple comparison. Here's a simple jQuery demo that makes use of the Star Wars API.

<h1>Star Wars Films</h1> <ul id="films"> </ul> <script> $(document).ready(function() { $.get('https://swapi.com/api/films', function(res) { let list = ''; res.results.forEach(function(r) { list += `<li>${r.title}</li>`; }); $('#films').html(list); }); }); </script>

In the sample above, I use $.get to hit the API and return a list of films. Then I generate a list of titles as li tag elements with that data and insert it all into a ul block.

Now, let's consider an example of this using Vue:

<div id="app"> <h1>Star Wars Films</h1> <ul> <li v-for="film in films">{{film.title}}</li> </ul> </div> <script> const app = new Vue({ el: '#app', data: { films: [] }, created() { fetch('https://swapi.com/api/films') .then(res => res.json()) .then(res => { this.films = res.results; }); } }) </script>

Probably the best part of this is the use of the v-for template. Notice how Vue isn't concerned with the layout (well, at least the JavaScript). The data is fetched from the API. It’s assigned a variable. The layout handles displaying it. I've always hated having HTML in my JavaScript and, while solutions exist for that with jQuery, having it baked into Vue makes it a natural fit.

A full (if somewhat trivial) example

To bring it home a bit, let's consider a more real world example. Our client has asked us to build a fancy Ajax-enabled front-end search interface to a product API. The feature list includes:

  • Support filtering by name and product category
  • Form validation such that we must supply a search term or a category
  • While the API is being hit, show a message to the user and disable the submit button
  • When done, handle reporting that no products were shown or list the matches

Let's begin with the jQuery version. First, the HTML:

<form> <p> <label for="search">Search</label> <input type="search" id="search"> </p> <p> <label for="category">Category</label> <select id="category"> <option></option> <option>Food</option> <option>Games</option> </select> </p> <button id="searchBtn">Search</button> </form> <div id="status"></div> <div id="results"></div>

There's a form with our two filters and two divs. One's used as a temporary status when searching or reporting errors and one is used to render results. Now, check out the code.

const productAPI = 'https://wt-c2bde7d7dfc8623f121b0eb5a7102930-0.sandbox.auth0-extend.com/productSearch'; $(document).ready(() => { let $search = $('#search'); let $category = $('#category'); let $searchBtn = $('#searchBtn'); let $status = $('#status'); let $results = $('#results'); $searchBtn.on('click', e => { e.preventDefault(); // First clear previous stuff $status.html(''); $results.html(''); // OK, now validate form let term = $search.val(); let category = $category.val(); if(term === '' && category === '') { $status.html('You must enter a term or select a category.'); return false; } $searchBtn.attr('disabled','disabled'); $status.html('Searching - please stand by...'); $.post(productAPI, { name:term, category:category }, body => { $searchBtn.removeAttr('disabled'); $status.html(''); if(body.results.length === 0) { $results.html('<p>Sorry, no results!</p>'); return; } let result = '<ul>'; body.results.forEach(r => { result += `<li>${r.name}</li>` }); result += '</ul>'; $results.html(result); }); }); });

The code begins by creating a set of variables for each of the DOM items we want to work with — the form fields, button, and divs. The core of the logic is within the click handler for the button. We do validation, and if everything is OK, do a POST request against the API. When it returns, we either render the results or show a message if nothing was matched.

You can work with a complete version of this demo using the CodePen below.

See the Pen
jQuery Full
by Raymond Camden (@cfjedimaster)
on CodePen.

Now let's consider the Vue version. Again, let's start with the layout:

<div id="app"> <form> <p> <label for="search">Search</label> <input type="search" v-model="search"> </p> <p> <label for="category">Category</label> <select v-model="category"> <option></option> <option>Food</option> <option>Games</option> </select> </p> <button @click.prevent="searchProducts" :disabled="searchBtnDisabled">Search</button> </form> <div v-html="status"></div> <ul v-if="results"> <li v-for="result in results">{{result.name}}</li> </ul> </div>

From the top, the changes include:

  • Wrapping the layout in a div that can be used to let Vue know where to work.
  • Using v-model for the form fields to make it easy to work with the data.
  • Using @click.prevent to handle doing the main search operation.
  • Using :disabled to bind whether or not the button is disabled to a value in the Vue application (we'll see that in action in a moment).
  • The status value is a bit different than earlier examples. While jQuery has a specific method to set text in a DOM item and another for HTML, Vue requires using v-html when assigning HTML to a value that's going to be rendered. If we tried to do {{status}} with HTML, the tags would be escaped.
  • Finally, using v-if to conditionally render a list of results along with v-for to handle the iteration.

Now let's look at the code.

const productAPI = 'https://wt-c2bde7d7dfc8623f121b0eb5a7102930-0.sandbox.auth0-extend.com/productSearch'; const app = new Vue({ el: '#app', data: { search: '', category: '', status: '', results: null, searchBtnDisabled: false }, methods: { searchProducts:function() { this.results = null; this.status = ''; if(this.search === '' && this.category === '') { this.status = 'You must enter a term or select a category.'; return; } this.searchBtnDisabled = true; this.status = 'Searching - please stand by...'; fetch(productAPI, { method: 'POST', headers: { 'Content-Type':'application/json' }, body: JSON.stringify({name:this.search,category:this.category}) }).then(res => res.json()) .then(res => { this.status = ''; this.searchBtnDisabled = false; this.results = res.results; if(this.results.length === 0) this.status = '<p>Sorry, no results!</p>'; }); } } });

The first block worth calling out is the set of data fields. Some map to form fields and others to results, status messages, and the like. The searchProducts method handles much of the same stuff as the jQuery version but, in general, there's much less code directly tied to the DOM. For example, even though we know the results are listed in an unordered list, the code itself doesn't worry about that. It simply assigns the value and the markup handles rendering it. Overall, the JavaScript code is much more concerned about logic in comparison to the jQuery code which "feels" like a much nicer separation of concerns.

As before, I've got a CodePen for you to try this out yourself:

See the Pen
Vue Full
by Raymond Camden (@cfjedimaster)
on CodePen.

Death to jQuery! Long Live Vue!

OK, that's a bit over the top. As I said in the beginning, I absolutely think that you shouldn't change a thing if like working with jQuery and it's working for you.

I can say, however, that Vue feels like a great "next step" for people who are used to working with jQuery. Vue supports complex applications and has a great command line tool for scaffolding and building projects. But for simpler tasks, Vue works as a great "modern jQuery" replacement that has become my tool of choice for development!

For another perspective on using Vue in place of jQuery, check out Sarah Drasner's "Replacing jQuery With Vue.js: No Build Step Necessary" because it includes a handful of other super helpful examples.

The post Making the Move from jQuery to Vue appeared first on CSS-Tricks.

Currently Reading: Progressive Web Apps by Jason Grigsby

Css Tricks - Fri, 05/03/2019 - 4:27am

I’ve been reading Jason Grigsby’s new book on progressive web apps this past week and it’s exciting. Jason explains what PWAs are and how they work while while doing a bang-up job covering the business case for using them them, too. But perhaps you might be thinking that a PWA isn’t necessary for the project you’re working on right now. Well, Jason argues that progressive web apps are for everybody:

Should your website be a progressive web app? The answer is almost certainly yes. Even if you don’t think of your website as an “app,” the core features of progressive web apps can benefit any website. Who wouldn’t profit from a fast, secure, and reliable website?

One of the challenges I’ve experienced when thinking about how to apply a progressive web app to a project I’m working on is figuring out what content to cache. Should the homepage be cached? Do we make a custom offline page? What is useful information to provide a user in that context?

Jason goes there, too, and even describes how he tackles that for his own projects:

For cloudfour.com, we chose to only cache recently viewed pages because the main reason people come to our site is to read the articles. If we tried to anticipate which articles someone would want offline access to, we’d likely guess incorrectly. If we precached top-level pages, we might force people on a metered network connection to download content they would never look at...

That makes a ton of sense to me and I realize that the offline cache should probably be different depending on the situation and the website. For example, maybe a design agency website could replace the big flashy homepage with an offline page that only shows the phone number of the agency instead. Or perhaps a restaurant website could cache the food menu and make that experience offline, but remove all the images to make sure it’s not too impactful for folks on those metered networks.

Anyway, I think that Jason’s book is wonderful as it reveals to us all this complexity and a whole new set of opportunities to improve the design and experience of our websites, which, by the way, is something we should strive for in this new and exciting age of web app development.

The post Currently Reading: Progressive Web Apps by Jason Grigsby appeared first on CSS-Tricks.

Making Web Components for Different Contexts

Css Tricks - Thu, 05/02/2019 - 8:09am

This article isn’t about how to build web components. Caleb Williams already wrote a comprehensive guide about that recently. Let’s talk about how to work with them, what to consider when making them, and how to embrace them in your projects.

If you are new to web components, Caleb’s guide is a great read, but here are more resources that will get you up to speed:

Since web components are now widely supported (thanks to the hard work of many people behind the scenes) — and considering the imminent switch that Edge will make to the chromium platform — people are now thinking about web components as "native" and a platform-compliant way to build reusable UI components to keep consistency across design systems and web projects, while using the power of the Shadow DOM to encapsulate style and logics inside the component itself.

Well, this can be true and false at the same time. But first, let’s get acquainted with the Abstraction Layers Triangle.

The Abstraction Layers Triangle

Technically, we should consider web components as an extension of our favorite markup language, HTML (yep!). The Web Components API allows us to create custom HTML elements (e.g. <foo-bar>) that don’t exist in HTML.

We are told web components are basically new HTML elements, so we should consider them as part of the HTML specifications and, consequently, we should follow its paradigms, core concepts, and utilization. If we assume all of these points, we will figure out that our components will live among the lowest levels of the web platform stack, alongside HTML, CSS, and JavaScript.

Frameworks and libraries like React, Vue, Angular, SvelteJS work on their abstraction level, right above other tools that live in a sort of "middle earth," like StencilJs, Hybrids and Lit. Under these layers of abstraction, we can find our basic web technologies… and vanilla web components. We can represent this concept with an ALT (A>bstraction L Triangle) diagram:

The higher we go, the more abstraction things get.

Why is this important? Well, it helps us visualize the various layers that exist on top of native components and understand the context they are used so that they can be built for an intended context. What's context? That's where we're headed.

Same technology, different contexts

The Shadow DOM is a key factor in the Web Components API. It allows us to bundle JavaScript and CSS inside a custom element to both prevent external interferences and style manipulations, unless we expressly allow it. There are indeed some approaches that developers can follow to allow external CSS to leak into the shadow root and into a component, including custom properties and the ::part and ::theme pseudo-elements, which is something Monica Dinculescu) has covered so well.

There is also another thing to consider: the context we are working with. After three years of building web components personally, I can identify two contexts: the private context (like a design system) and the standard context (like plain HTML, CSS, and JavaScript without custom styles).

Before designing components, we need to know how they will be used, so determining the type of context is a key to all of this. The most easy way is targeting only one context, but with a small CSS trick. we can build our components for both of them.

Let’s look at the differences between the two contexts before we get into that.

Private context

A private context is a closed ecosystem that provides components with their own style that must be used as-is. So, if we are building a component library that comes from specific styling guidelines or a design system, each component will reflect custom styles so there’s no need to code them up each time they’re needed.

That can be true also with JavaScript logic. For example, we can attach a closed shadow root that prevent others to accidentally pierce the shadow boundary with a querySelector. As a a result, we can simply pick and use all any component, avoiding issues like style inconsistencies and CSS collisions. As the author, you can also get to define a set of CSS custom properties (or ::parts) that can be used to style a component for a specific use case, but this is not the focus point of a design system.

Here’s an example of a web component component in a private context. It has all of the styles and logic contained inside its shadow-root and and can simply be dropped into any page.

See the Pen
Closed Context Web Component
by Mattia Astorino (@equinusocio)
on CodePen.

This example and the one to follow are for demonstration purposes and not intended for production use because they do not make considerations for key situations, like accessibility and other optimizations.

Components in a private context can be rarely used outside of that context. For example, if we try to take an element from a design system (which has its own enforced styles), we’re unable to simply add it to a project and expect to customize it. You know how Bootstrap can be themed and customized to your liking? This is pretty much the opposite of that. These components are made to live inside their context and their context only.

Standard context

A standard context may be the most complex type of component, not only because the environment can range anywhere from a full-fledged framework (like Vue and React) to plain vanilla HTML, but also because everyone should be able to use that component like any other element.

For example, when adding a component publicly, say to npm, those who use it will expect to be able to customize it, at least to some degree.

Do you know of any HTML element that comes with its own presentational style? The answer should be no because, well, elements must be explicitly styled with CSS. This is also true for web components made in a standard context. A single web component should be customizable by adding classes an attributes, or other methods.

Here’s the same <todo-list> element that we saw in the closed context example, but designed for a standard context. It works as-is, without any presentational styles inside its shadow root. In fact, it only contains the required logic and baseline CSS to make sure it functions. Otherwise, it’s completely customizable like any standard HTML element, like a div.

See the Pen
Standard Context Web Component
by Mattia Astorino (@equinusocio)
on CodePen.

Both of the examples we’ve looked at for each context are made with the same component. The difference is that the component in a standard context an be customized and selected with external CSS.

Web components and composition

OK, so working with web components is really the same as working with plain HTML, though as we’ve seen, it’s important to follow the paradigms and principles of the given content. Well, thing we need to be mindful of is the web component composition.

As explained by Google Web Fundamentals:

Composition is one of the least understood features of shadow DOM, but it's arguably the most important.

In our world of web development, composition is how we construct apps, declaratively out of HTML. Different building blocks (<div>s, <header>s, <form>s, <input>s) come together to form apps. Some of these tags even work with each other. Composition is why native elements like <select>, <details>, <form>, and <video> are so flexible. Each of those tags accepts certain HTML as children and does something special with them. For example, <select> knows how to render option> and <optgroup> into dropdown and multi-select widgets. The <details> element renders <summary> as an expandable arrow. Even <video> knows how to deal with certain children: <source> elements don't get rendered, but they do affect the video's behavior. What magic!

Composition is what we normally do when we work with HTML. Since web components are merely HTML elements with a DOM reference — and not logical containers — we should rely on composition to build our components and any sub-components. If you think about the ul and and select you will notice that you declaratively compose these elements to get the final output and you have specific attributes to be used with the main component (e.g. [readonly]) or the sub-component (e.g. [selected]). This is true also for web components, and if you are building a custom list, consider to build the main component (<custom-list>) and the child one (<custom-li>). Using the [slot] element, you can define where children elements will be placed and also placeholder content that will be shown when no children are passed through.

Web components and accessibility

Another thing to consider is that "small" topic we call accessibility. Since we are creating completely new HTML elements, we need to consider the accessibility of our elements in order to provide a basic semantic role, any keyboard navigation as well as the user’s operating system preferences, like the reduce motion and high contrast settings.

I strongly suggest the following resources as reference for building accessible and inclusive components, how to define semantic markup, and how to implement a basic keyboard navigation.

Conclusion

Web components are an emerging technology in web development and, as such, there really aren’t any clearly defined best practices to guide us as far as building them for their intended or maximized use. When you find yourself working with them, perhaps the single thing you can take away from this post is to consider whether they are intended for a closed context or a standard context, then ask yourself WHI:

  • Who will use this component?
  • How much flexibility should that person have to customize it?
  • Is this component for everyone or for a specific audience?

The post Making Web Components for Different Contexts appeared first on CSS-Tricks.

Split

Css Tricks - Thu, 05/02/2019 - 8:08am

Jeremy on the divide between the core languages of the web, and all the tooling that exists to produce code in those languages:

On the one hand, you’ve got the raw materials of the web: HTML, CSS, and JavaScript. This is what users will ultimately interact with.

On the other hand, you’ve got all the tools and technologies that help you produce the HTML, CSS, and JavaScript: pre-processors, post-processors, transpilers, bundlers, and other build tools.

Jeremy likes the raw materials side the best but acknowledges a healthy balance of both worlds is a healthy mix.

I think a great front-end developer is hyper-aware of this split. Every choice we make is a trade-off between developer productivity and complexity management and the user's experience. The trick is to punish the user as little as possible while giving yourself as much as you can.

Direct Link to ArticlePermalink

The post Split appeared first on CSS-Tricks.

Easily Turn Your Photos into Vectors with Photo Vectorizer

Css Tricks - Thu, 05/02/2019 - 4:39am

(This is a sponsored post.)

Photo Vectorizer is a simple-to-use Photoshop action that can convert any photo into a vector. With just a few clicks of your mouse, you can save tons of time and frustration by turning your photos into vectors. With super sharp results, these vectors are great for any project either online or in print.

Highlights:

  • Turn your photos into professional looking vectors.
  • Easy to use — just a few clicks.
  • Save tons of time.
  • Sharp, clean results.
  • Great for backgrounds, spot illustrations and presentations as well as printed projects like T- shirts, mugs, totes and more.

Visit Site

Direct Link to ArticlePermalink

The post Easily Turn Your Photos into Vectors with Photo Vectorizer appeared first on CSS-Tricks.

Naming things to improve accessibility

Css Tricks - Wed, 05/01/2019 - 1:23pm

I like the this wrap-up statement from Hidde de Vries:

In modern browsers, our markup becomes an accessibility tree that ultimately informs what our interface looks like to assistive technologies. It doesn’t matter as much whether you’ve written this markup:

  • in a .html file
  • in Twig, Handlebars or Nunjucks
  • as the <template> in a Vue Single File Component
  • exported in the JSX of your React component
  • outputted by a weird legacy CMS

It is which markup that determines if your site is pleasurable to experience for AT users. In short: it’s the markup that matters

As a front-end developer, you'll find yourself writing markup in lots of different places with lots of different technologies. I think it behooves you think of how best to write it regardless of where and how.

Direct Link to ArticlePermalink

The post Naming things to improve accessibility appeared first on CSS-Tricks.

The Many Ways of Getting Data Into Charts

Css Tricks - Wed, 05/01/2019 - 4:31am

Data is available everywhere nowadays, whether it’s in a plain text file, a REST API, an online Google sheet… you name it! It’s that variety of context that makes building graphs more than simply having a database in your local project — where there is data, there is a way.

That’s pretty much what we’re going to look at in this post: making JavaScript data visualizations using data from a variety of sources.

If you want to follow along and make any of the visualizations we’re covering here, we’ll be using Chart.js so grab that and include it in your own environment:

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.js"></script> Source 1: HTML data table

Lots and lots of websites have data tables, and why not? They are a great way to show data and that’s what they were made to do. But, if you could have a visualization powered by the data in it — and for not much more effort — wouldn’t that be even better?

With a little JavaScript, the data in a HTML table can be isolated from the HTML and prepped for a chart. Look at the following data table:

Year Items Sold Turnover ($) Profit ($) 2016 10 200 89 2017 25 550 225 2018 55 1200 600 2019 120 2450 1100

It contains sales data for a business. Now, if we could graph this out, it would be both visually compelling and help users glean insights. So let’s do it!

First of all, let’s define a function for our chart. This comes straight out of the Chart.js library, so it’s worth cross-referencing this with the documentation is something seems unclear. I’ve added some comments to call out key parts.

function BuildChart(labels, values, chartTitle) { var ctx = document.getElementById("myChart").getContext('2d'); var myChart = new Chart(ctx, { type: 'bar', data: { labels: labels, // Our labels datasets: [{ label: chartTitle, // Name the series data: values, // Our values backgroundColor: [ // Specify custom colors 'rgba(255, 99, 132, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)', 'rgba(75, 192, 192, 0.2)', 'rgba(153, 102, 255, 0.2)', 'rgba(255, 159, 64, 0.2)' ], borderColor: [ // Add custom color borders 'rgba(255,99,132,1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)', 'rgba(75, 192, 192, 1)', 'rgba(153, 102, 255, 1)', 'rgba(255, 159, 64, 1)' ], borderWidth: 1 // Specify bar border width }] }, options: { responsive: true, // Instruct chart js to respond nicely. maintainAspectRatio: false, // Add to prevent default behavior of full-width/height } }); return myChart; }

Now that we have a function to create a chart for the table data, let’s write out the HTML for the table and add a canvas element that Chart.js can use to inject its charting magic. This is exactly the same data from the table example above.

<table class="table" id="dataTable"> <thead> <th>Year</th> <th>Items Sold</th> <th>Turnover ($)</th> <th>Profit ($)</th> </thead> <tbody> <tr> <td>2016</td> <td>10</td> <td>200</td> <td>89</td> </tr> <tr> <td>2017</td> <td>25</td> <td>550</td> <td>225</td> </tr> <tr> <td>2018</td> <td>55</td> <td>1200</td> <td>600</td> </tr> <tr> <td>2019</td> <td>120</td> <td>2450</td> <td>1100</td> </tr> </tbody> </table> <div class="chart"> <canvas id="myChart"></canvas> </div>

Then, we need to parse the table into JSON with vanilla JavaScript. This is what Chart.js will use to populate the charts and graphs.

var table = document.getElementById('dataTable'); var json = []]; // First row needs to be headers var headers =[]; for (var i = 0; i < table.rows[0].cells.length; i++) { headers[i] = table.rows[0].cells[i].innerHTML.toLowerCase().replace(/ /gi, ''); } // Go through cells for (var i = 1; i < table.rows.length; i++) { var tableRow = table.rows[i]; var rowData = {}; for (var j = 0; j < tableRow.cells.length; j++) { rowData[headers[j]] = tableRow.cells[j].innerHTML; } json.push(rowData); } console.log(json);

We threw in that last line so we can check the output in the DevTools console. Here’s what is logged into the console:

Perfect! Our table headers become variables and are mapped to the content in the table cells.

All that’s left to do is map the year labels and items sold values to array (which Chart.js requires for its data object) and then to pass the data into the chart function.

This script maps the JSON values to an array of years. We can add it directly after the previous function.

// Map JSON values back to label array var labels = json.map(function (e) { return e.year; }); console.log(labels); // ["2016", "2017", "2018", "2019"] // Map JSON values back to values array var values = json.map(function (e) { return e.itemssold; }); console.log(values); // ["10", "25", "55", "120"]

Call the BuildChart function from our first snippet (including a name for the chart) and we get a beautiful visualization of the data from the HTML table.

var chart = BuildChart(labels, values, "Items Sold Over Time");

And that is it! The charts data has now been isolated and passed into the JavaScript visualization and rendered.

See the Pen
BarChart Loaded From HTML Table
by Danny Englishby (@DanEnglishby)
on CodePen.

Source 2: A real-time API

There are many, many public APIs available in the world, many of which are rich with neat and useful data. Let’s use one of them to demonstrate how real-time data can be used to populate a chart. I’m going to use the Forbes 400 Rich List API to graph out the top 10 richest people in the world. I know, cool, eh?! I always find wealth rankings interesting, and there is so much more data this API provides. But for now, we will request data to display a chart with names and real time net worth using pure JavaScript!

First off, we want to define a chart function again, this time with a few more options.

function BuildChart(labels, values, chartTitle) { var data = { labels: labels, datasets: [{ label: chartTitle, // Name the series data: values, backgroundColor: ['rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', ], }], }; var ctx = document.getElementById("myChart").getContext('2d'); var myChart = new Chart(ctx, { type: 'horizontalBar', data: data, options: { responsive: true, // Instruct chart JS to respond nicely. maintainAspectRatio: false, // Add to prevent default behavior of full-width/height scales: { xAxes: [{ scaleLabel: { display: true, labelString: '$ Billion' } }], yAxes: [{ scaleLabel: { display: true, labelString: 'Name' } }] }, } }); return myChart; }

Next, we’ll need that same HTML canvas element for where the chart will be rendered:

<div class="chart" style="position: relative; height:80vh; width:100vw"> <canvas id="myChart"></canvas> </div>

Now to grab some real time data. Let’s see what is returned in the console from the Forbes API call:

As you can see by the JSON returned, there is a lot of rich information that can injected into a chart. So, let’s make our rankings!

With some light JavaScript, we can request the data from the API, pick out and map the values we went to array variables, and finally pass our data in and rendering the chart.

var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { var json = JSON.parse(this.response); // Map JSON labels back to values array var labels = json.map(function (e) { return e.name; }); // Map JSON values back to values array var values = json.map(function (e) { return (e.realTimeWorth / 1000); // Divide to billions in units of ten }); BuildChart(labels, values, "Real Time Net Worth"); // Pass in data and call the chart } }; xhttp.open("GET", "https://forbes400.herokuapp.com/api/forbes400?limit=10", false); xhttp.send();

See the Pen
Chart Loaded From RichListAPI
by Danny Englishby (@DanEnglishby)
on CodePen.

Source 3: A Google Sheet

So far, we’ve looked at data in standard HTML tables and APIs to populate charts. But what if we already have an existing Google Sheet that has a bunch of data in it? Well, we can also use that to make a chart!

First, there are some rules for accessing a Google Sheet:

  • The Google Sheet must be published
  • The Google Sheet must be public (i.e. not set to private viewing)

As long as these two points are true, we can access a Google Sheet in the form of JSON, which means, of course, we can graph it out!

Here’s a Google Sheet with some made up data that I’ve published publicly. It consists of three fields of data: MachineId, Date, and ProductsProduced.

Now, if we that the sheet’s URL, we’ll want to note everything after the last slash:

https://docs.google.com/spreadsheets/d/1ySHjH6IMN0aKImYcuVHozQ_TvS6Npt4mDxpKDtsFVFg

This is the sheet identity and what we need for the GET request we send to Google. To make a GET request for JSON, we insert that string in the URL in another URL:

https://spreadsheets.google.com/feeds/list/[ID GOES HERE]/od6/public/full?alt=json

That gives us the following URL:

https://spreadsheets.google.com/feeds/list/1ySHjH6IMN0aKImYcuVHozQ_TvS6Npt4mDxpKDtsFVFg/od6/public/full?alt=json

And here’s the response we get in the console:

The important piece is the feed.entry object array. This holds vital sheet data, which looks like this when we drill into it:

Notice the items underlined in red. The Google Sheets API has preceded each of the column names with gsx$ (e.g. gsx$date). These are exactly how we will dissect the data from the object, using these uniquely generated names. So, knowing this, it’s time to insert the data into some isolated arrays and pass them into our chart function.

function BuildChart(labels, values, chartTitle) { var data = { labels: labels, datasets: [{ label: chartTitle, // Name the series data: values, backgroundColor: ['rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', 'rgb(54, 162, 235)', ], }], }; var ctx = document.getElementById("myChart").getContext('2d'); var myChart = new Chart(ctx, { type: 'bar', data: data, options: { responsive: true, // Instruct chart js to respond nicely. maintainAspectRatio: false, // Add to prevent default behavior of full-width/height scales: { xAxes: [{ scaleLabel: { display: true, labelString: 'Date' } }], yAxes: [{ scaleLabel: { display: true, labelString: 'Produced Count' } }] }, } }); return myChart; }

And, you guessed it, next is the Canvas element:

<div class="chart" style="position: relative; height:80vh; width:100vw"> <canvas id="myChart"></canvas> </div>

...then the GET request, mapping our labels and values array and finally calling the chart passing in the data.

var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { var json = JSON.parse(this.response); console.log(json); // Map JSON labels back to values array var labels = json.feed.entry.map(function (e) { return e.gsx$date.$t; }); // Map JSON values back to values array var values = json.feed.entry.map(function (e) { return e.gsx$productsproduced.$t; }); BuildChart(labels, values, "Production Data"); } }; xhttp.open("GET", "https://spreadsheets.google.com/feeds/list/1ySHjH6IMN0aKImYcuVHozQ_TvS6Npt4mDxpKDtsFVFg/od6/public/full?alt=json", false); xhttp.send();

And, boom!

See the Pen
Chart Loaded From a Google Sheet
by Danny Englishby (@DanEnglishby)
on CodePen.

What will you make with data?

You probably get the point that there is a variety of ways we can get data to populate beautiful looking charts and graphs. As long as we have some formatted numbers and a data visualization library, then we have a lot of powers at our fingertips.

Hopefully now you’re thinking of where you might have data and how to plug into a chart! We didn’t even cover all of the possibilities here. Here are a few more resources you can use now that you’ve got chart-making chops.

A few more charting libraries A few more places to store data

The post The Many Ways of Getting Data Into Charts appeared first on CSS-Tricks.

Earth day, API’s and sunshine.

Css Tricks - Wed, 05/01/2019 - 4:31am

Cassie Evans showcases some really nifty web design ideas and explores using the API provided by the company her team over at Clearleft recently hired to cover their building's roof with solar panels. Cassie outlines her journey designing a webpage that uses the API to populate some light data visualizations about the energy the building uses now that the solar panels are installed.

Here at Clearleft we’ve been taking small steps to reduce our environmental impact. In December 2018 we covered the roof of our home with solar panels.

With the first of the glorious summer sun starting to shine down on us, we started to ponder about what environmental impact they'd had over the last 5 months.

Luckily for us, our solar panels have an API, so we can not only find out that information, we can request it from SolarEdge and display it in our very own interface.

The post is a great practical look into using the Fetch API which is also something Zell Liew wrote up in thorough detail, covering the history of using APIs with JavaScript, handling errors and other weird things that might happen when working with it.

But, equally interesting and useful is reading through Cassie's thought process as she sketches a wireframe for the page, researches how to use the Fetch API, and integrates animation into a lovely SVG illustration. It's an exercise in both design and development that many of us can relate to but also learn from.

Oh and while we're on the topic of data visualizations, Dan Englishby posted something just today on the many ways if getting data into charts. Working with real-time APIs is covered there as well, and is a nice segue from Cassie's post.

Direct Link to ArticlePermalink

The post Earth day, API’s and sunshine. appeared first on CSS-Tricks.

The Simplest Ways to Handle HTML Includes

Css Tricks - Tue, 04/30/2019 - 11:47am

It's extremely surprising to me that HTML has never had any way to include other HTML files within it. Nor does there seem to be anything on the horizon that addresses it. I'm talking about straight up includes, like taking a chunk of HTML and plopping it right into another. For example the use case for much of the entire internet, an included header and footer for all pages:

... <body> <include src="./header.html"></include> Content <include src="./footer.html"></include> </body> ...

That's not real, by the way. I just wish it was.

People have been looking to other languages to solve this problem for them forever. It's HTML preprocessing, in a sense. Long before we were preprocessing our CSS, we were using tools to manipulate our HTML. And we still are, because the idea of includes is useful on pretty much every website in the world.

Use PHP

Can you use PHP instead?

... <body> <?php include "./header.html" ?> Content <?php include "./footer.html" ?> </body> ...

This will perform the include at the server level, making the request for it happen at the file system level on the server, so it should be far quicker than a client-side solution.

Use Gulp

What's even faster than a server-side include? If the include is preprocessed before it's even on the server. Gulp has a variety of processors that can do this. One is gulp-file-include.

That would look like this:

... <body> @@include('./header.html') Content @@include('./footer.html') </body> ...

And you'd process it like:

var fileinclude = require('gulp-file-include'), gulp = require('gulp'); gulp.task('fileinclude', function() { gulp.src(['index.html']) .pipe(fileinclude({ prefix: '@@', basepath: '@file' })) .pipe(gulp.dest('./')); });

Looks like this particular plugin has fancy features where you can pass in variables to the includes, making it possible to make little data-driven components.

Use Grunt

This is what the grunt-bake plugin does. You'd configure Grunt to process your HTML:

grunt.initConfig({ bake: { your_target: { files: { "dist/index.html": "app/index.html", } } } });

Then your HTML can use this special syntax for includes:

... <body> <!--(bake header.html)--> Content <!--(bake footer.html)--> </body> ... Use Handlebars

Handlebars has partials.

You register them:

Handlebars.registerPartial('myPartial', '{{name}}')

Then use them:

{{> myPartial }}

There is also fancy features of this that allow for evaluation and passing data. You'll still need a processor to run it, probably something like gulp-handlebars.

Speaking of templating languages which make use of curly braces... Mustache has them, too.

Use Pug

Pug is an HTML preprocessor that has a whole new syntax for HTML that is a bit more terse. It's got includes though.

... body include ./header.html" p Content include ./footer.html" ...

Then you run it with something like gulp-pug.

Use Nunjucks

I love me some Nunjucks! Nunjucks has includes. You'd do it like this:

... <body> {% include "./header.html" %} Content {% include "./footer.html" %} </body> ...

If you put that in a file called index.njk, you could process it with a simple Node script into index.html like this:

const nunjucks = require("nunjucks"); const fs = require("fs"); fs.writeFile("index.html", nunjucks.render("index.njk"), function(err, data) { if (err) console.log(err); console.log("Compiled the Nunjucks, captain."); });

Or process it with something like gulp-nunjucks.

11ty has Nunjucks built-in, along with many of the other mentioned so far. Might be good for you if you're actually building a little site.

Use Ajax

Say you had...

<body> <header></header> Content. <footer></footer> </body>

You could fetch the contents for the header and footer from respective files and dump the contents in.

fetch("./header.html") .then(response => { return response.text() }) .then(data => { document.querySelector("header").innerHTML = data; }); fetch("./footer.html") .then(response => { return response.text() }) .then(data => { document.querySelector("footer").innerHTML = data; });

Speaking of JavaScript... If you're building your site using a JavaScript framework of just about any kind, building through components is kind of the main deal there and breaking parts you want to include in other files should be no problem. Some kind of import Header from "./header.js"; and <Header /> is the territory you'd be in in React land.

Use iframes

You could do this:

<body> <iframe src="./header.html"></iframe> Content. <iframe src="./footer.html"></iframe> </body>

But the content in those iframes does not share the same DOM, so it's a bit weird, not to mention slow and awkward to style (since iframes don't know the heights of their contents).

Scott Jehl documented a cool idea though: You can have the iframe inject the content of itself onto the parent page then remove itself.

<body> <iframe src="header.html" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"></iframe> Content. <iframe src="footer.html" onload="this.before((this.contentDocument.body||this.contentDocument).children[0]);this.remove()"></iframe> </body> Use Jekyll

Jekyll is a Ruby-based static site generator with includes. You keep your includes in the /_includes/ folder, then:

<body> {% include header.html %} Content. {% include footer.html %} </body>

Jekyll is a big one, so I'm calling it out here, but there are a ton of static site generators and I'd wager any of them can do includes.

Use Sergey

OK, I'll call out one more SSG because it's new and super focused. Sergey has a web components style format:

<body> <sergey-import src="header" /> Content. <sergey-import src="footer" /> </body>

You'd name the files header.html and footer.html and put them in /includes/ and then it'll make a build with the includes processed when you run the npm script it has you do.

Use Apache SSI

Apache, a super duper common web server, can do includes. You do it like this:

<body> <!--#include file="./header.html" --> Content <!--#include file="./footer.html" --> </body>

But you need the right Apache configuration to allow stuff. I tried my best to get a working demo going but didn't have much luck.

I tried using .htaccess within a folder on an Apache server and flipping on what I thought was the right stuff:

Options +Includes AddType text/html .html AddOutputFilter INCLUDES .html

I'm sure there is some way to get it working though, and if you do, it's kinda neat that it needs zero other dependencies.

Use CodeKit

Mac only, but CodeKit has a special language called Kit it processes where 90% of the point of it is HTML includes. It uses special HTML comments:

... <body> <!-- @import "./header.html" --> Content <!-- @import "./footer.html" --> </body> ... Use Dreamweaver

Lol jk. But it really is a thing. DWTs, baby.

Holy Crap

That's a lot of ways, isn't it?

Like I said at the top, it's very surprising to me that HTML itself hasn't addressed this directly. Not that I think it would be a great idea for performance to have <include> statements that trigger network requests all over our code, but it seems in-line with the platform. Using ES6 imports directly without bundling isn't a great idea always either, but we have them. @importing CSS within CSS isn't a great idea always, but we have it. If the platform had a native syntax, perhaps other tooling would key off that, much like JavaScript bundlers support the ES6 import format.

The post The Simplest Ways to Handle HTML Includes appeared first on CSS-Tricks.

Syndicate content
©2003 - Present Akamai Design & Development.