Archiwum kategorii: CSS

Innovation Can’t Keep the Web Fast

Post pobrano z: Innovation Can’t Keep the Web Fast

Every so often, the fruits of innovation bear fruit in the form of improvements to the foundational layers of the web. In 2015, HTTP/2 became a published standard in an effort to update an aging protocol. This was was both necessary and overdue, as HTTP/1 rendered web performance as an arcane sort of discipline in the form of strange workarounds of its limitations. Though HTTP/2 proliferation isn’t absolute — and there are kinks yet to be worked out — I don’t think it’s a stretch to say the web is better off because of it.

Unfortunately, the rollout of HTTP/2 has presided over a 102% median increase of bytes transferred over mobile the last four years. If we look at the 90th percentile of that same dataset — because it’s really the long tail of performance we need to optimize for — we see an increase of 239%. From 2016 (PDF warning) to 2019, the average mobile download speed in the U.S. has increased by 73%. In Brazil and India, average mobile download speeds increased by 75% and 28%, respectively, in that same period of time.

While page weight alone doesn’t necessarily tell the whole story of the user experience, it is, at the very least, a loosely related phenomenon which threatens the collective user experience. The story that HTTPArchive tells through data acquired from the Chrome User Experience Export (CrUX) can be interpreted a number of different ways, but this one fact is steadfast and unrelenting: most metrics gleaned from CrUX over the last couple of years show little, if any improvement despite various improvements in browsers, the HTTP protocol, and the network itself.

Given these trends, all that can be said of the impact of these improvements at this point is that it has helped to stem the tide of our excesses, but precious little to reduce them. Despite every significant improvement to the underpinnings of the web and the networks we access it through, we continue to build for it in ways that suggest we’re content with the never-ending Jevons paradox in which we toil.

If we’re to make progress in making a faster web for everyone, we must recognize some of the impediments to that goal:

  1. The relentless desire to monetize every square inch of the web, as well as the army of third party vendors which fuel the research mandated by such fevered efforts.
  2. Workplace cultures that favor unrestrained feature-driven development. This practice adds to — but rarely takes away from — what we cram down the wire to users.
  3. Developer conveniences that make the job of the developer easier, but can place an increasing cost on the client.

Counter-intuitively, owners of mature codebases which embody some or all of these traits continue to take the same unsustainable path to profitability they always have. They do this at their own peril, rather than acknowledge the repeatedly established fact that performance-first development practices will do as much — or more — for their bottom line and the user experience.

It’s with this understanding that I’ve come to accept that our current approach to remedy poor performance largely consists of engineering techniques that stem from the ill effects of our business, product management, and engineering practices. We’re good at applying tourniquets, but not so good at sewing up deep wounds.

It’s becoming increasingly clear that web performance isn’t solely an engineering problem, but a problem of people. This is an unappealing assessment in part because technical solutions are comparably inarguable. Content compression works. Minification works. Tree shaking works. Code splitting works. They’re undeniably effective solutions to what may seem like entirely technical problems.

The intersection of web performance and people, on the other hand, is messy and inconvenient. Unlike a technical solution as clearly beneficial as HTTP/2, how do we qualify what successful performance cultures look like? How do we qualify successful approaches to get there? I don’t know exactly what that looks like, but I believe a good template is the following marriage of cultural and engineering tenets:

  1. An organization can’t be successful in prioritizing performance if it can’t secure the support of its leaders. Without that crucial element, it becomes extremely difficult for organizations to create a culture in which performance is the primary feature of their product.
  2. Even with leadership support, performance can’t be effectively prioritized if the telemetry isn’t in place to measure it. Without measurement, it becomes impossible to explain how product development affects performance. If you don’t have the numbers, no one will care about performance until it becomes an apparent crisis.
  3. When you have the support of leadership to make performance a priority and the telemetry in place to measure it, you still can’t get there unless your entire organization understands web performance. This is the time at which you develop and roll out training, documentation, best practices, and standards the organization can embrace. In some ways, this is the space which organizations have already spent a lot of time in, but the challenging work is in establishing feedback loops to assess how well they understand and have applied that knowledge.
  4. When all of the other pieces are finally in place, you can start to create accountability in the organization around performance. Accountability doesn’t come in the form of reprisals when your telemetry tells you performance has suffered over time, but rather in the form of guard rails put in place in the deployment process to alert you when thresholds have been crossed.

Now comes the kicker: even if all of these things come together in your workplace, good outcomes aren’t guaranteed. Barring some regulation that forces us to address the poorly performing websites in our charge — akin to how the ADA keeps us on our toes with regard to accessibility — it’s going to take continuing evangelism and pressure to ensure performance remains a priority. Like so much of the work we do on the web, the work of maintaining a good user experience in evolving codebases is never done. I hope 2020 is the year that we meaningfully recognize that performance is about people, and adapt accordingly.

As technological innovations such as HTTP/3 and 5G emerge, we must take care not to rest on our laurels and simply assume they will heal our ills once and for all. If we do, we’ll certainly be having this discussion again when the successors to those technologies loom. Innovation alone can’t keep the web fast because making the web fast — and keeping it that way — is the hard work we can only accomplish by working together.

The post Innovation Can’t Keep the Web Fast appeared first on CSS-Tricks.

Smaller HTML Payloads with Service Workers

Post pobrano z: Smaller HTML Payloads with Service Workers

Short story: Philip Walton has a clever idea for using service workers to cache the top and bottom of HTML files, reducing a lot of network weight.

Longer thoughts: When you’re building a really simple website, you can get away with literally writing raw HTML. It doesn’t take long to need a bit more abstraction than that. Even if you’re building a three-page site, that’s three HTML files, and your programmer’s mind will be looking for ways to not repeat yourself. You’ll probably find a way to „include” all the stuff at the top and bottom of the HTML, and just change the content in the middle.

I have tended to reach for PHP for that sort of thing in the past (<?php include('header.php); ?>), although these days I’m feeling much more Jamstack-y and I’d probably do it with Eleventy and Nunjucks.

Or, you could go down the SPA (Single Page App) route just for this basic abstraction if you want. Next and Nuxt are perhaps a little heavy-handed for a few includes, but hey, at least they are easy to work with and the result is a nice static site. The thing about these JavaScript-powered SPA frameworks (Gatsby is in here, too), is that they „hydrate” from static sites into SPAs as the JavaScript loads. Part of the reason for that is speed. No longer does the browser need to reload and request a whole big HTML page again to render; it just asks for whatever smaller amount of data it needs and replaces it on the fly.

So in a sense, you might build a SPA because you have a common header and footer and just want to replace the guts, for efficiencies sake.

Here’s Phil:

In a traditional client-server setup, the server always needs to send a full HTML page to the client for every request (otherwise the response would be invalid). But when you think about it, that’s pretty wasteful. Most sites on the internet have a lot of repetition in their HTML payloads because their pages share a lot of common elements (e.g. the <head>, navigation bars, banners, sidebars, footers etc.). But in an ideal world, you wouldn’t have to send so much of the same HTML, over and over again, with every single page request.

With service workers, there’s a solution to this problem. A service worker can request just the bare minimum of data it needs from the server (e.g. an HTML content partial, a Markdown file, JSON data, etc.), and then it can programmatically transform that data into a full HTML document.

So rather than PHP, Eleventy, a JavaScript framework, or any other solution, Phil’s idea is that a service worker (a native browser technology) can save a cache of a site’s header and footer. Then server requests only need to be made for the „guts” while the full HTML document can be created on the fly.

It’s a super fancy idea, and no joke to implement, but the fact that it could be done with less tooling might be appealing to some. On Phil’s site:

 on this site over the past 30 days, page loads from a service worker had a 47.6% smaller network payloads, and a median First Contentful Paint (FCP) that was 52.3% faster than page loads without a service worker (416ms vs. 851ms).

Aside from configuring a service worker, I’d think the most finicky part is having to configure your server/API to deliver a content-only version of your stuff or build two flat file versions of everything.

Direct Link to ArticlePermalink

The post Smaller HTML Payloads with Service Workers appeared first on CSS-Tricks.

Sticky Table of Contents with Scrolling Active States

Post pobrano z: Sticky Table of Contents with Scrolling Active States

Say you have a two-column layout: a main column with content. Say it has a lot of content, with sections that requires scrolling. And let’s toss in a sidebar column that is largely empty, such that you can safely put a position: sticky; table of contents over there for all that content in the main column. A fairly common pattern for documentation.

Bramus Van Damme has a nice tutorial on all this, starting from semantic markup, implementing most of the functionality with HTML and CSS, and then doing the last bit of active nav enhancement with JavaScript.

For example, if you don’t click yourself down to a section (where you might be able to get away with :target styling for active navigation), JavaScript is necessary to tell where you are scrolled to an highlight the active navigation. That active bit is handled nicely with IntersectionObserver, which is, like, the perfect API for this.

Here’s that result:

CodePen Embed Fallback

It reminds me of a very similar demo from Hakim El Hattab he called Progress Nav. The design pattern is exactly the same, but Hakim’s version has this ultra fancy SVG path that draws itself along the way, indenting for sub nav. I’ll embed a video here:

That one doesn’t use IntersectionObserver, so if you want to hack on this, combine ’em!

The post Sticky Table of Contents with Scrolling Active States appeared first on CSS-Tricks.

Playwright

Post pobrano z: Playwright

So Microsoft launches a Node-based browser automation project called Playwright. It allows you to spin up a headless version of a browser and control it. Go here! Click something! Take a screenshot! That kind of stuff. Particularly useful for testing.

It’s just like Google’s Puppeteer, only instead of being Chrome-only, it also „works” in Firefox and Safari.

The drama started immediately.

The launch tweet from Andrey Lushnikov (who’s Twitter bio is „former TL @ Chrome Puppeteer, former eng @ Chrome DevTools”), is responded to by Sam Sneddon who questions the cross-browser compatibility. Apparently that compatibility comes via very large patches to those other browsers which some feel are a little house-of-cards-esque and will never actually land in those other browsers, especially since there are competing efforts like puppeteer-firefox.

It’s fairly obvious that the original team from Google behind Puppeteer kinda, uhhhh, made their way over to Microsoft and re-did the work over there. A little bird tells me Google is proper pissed about it.

I don’t have any other inside knowledge here, but it doesn’t seem to make Microsoft look very good here. For a company that has had so much success with an open-source strategy, hiring away a team to build a directly competing alternate open-source project without much cooperation from the other open-source projects it integrates with isn’t a great look. At the same time, having a working project that allows cross-browser headless control is pretty rad.

Feel free to enlighten me if I have it all wrong.

Related: As I understand it, Cypress doesn’t use either project, but has their own thing, and is close to Firefox support as well.

Direct Link to ArticlePermalink

The post Playwright appeared first on CSS-Tricks.

Bundling JavaScript for Performance: Best Practices

Post pobrano z: Bundling JavaScript for Performance: Best Practices

Performance advice from David Calhoun on how many scripts to load on a page for best performance:

[…] some of your vendor dependencies probably change slower than others. react and react-dom probably change the slowest, and their versions are always paired together, so they both form a logical chunk that can be kept separate from other faster-changing vendor code:

<!-- index.html -->
<script src="vendor.react.[hash].min.js"></script>
<script src="vendor.others.[hash].min.js"></script>
<script src="index.[hash].min.js"></script>

Funny how times haven’t changed that much! Me, in 2012, talking about how many CSS files need to be loaded on any given page: One, Two, or Three. I split it into global, section-specific, and-page-specific so it was less about third-party code, although that could certainly apply, too.

Direct Link to ArticlePermalink

The post Bundling JavaScript for Performance: Best Practices appeared first on CSS-Tricks.

What’s the Difference Between Width/Height in CSS and Width/Height HTML attributes?

Post pobrano z: What’s the Difference Between Width/Height in CSS and Width/Height HTML attributes?

Some HTML elements accept width and height as attributes. Some do not. For example:

<!-- valid, works, is a good idea -->
<img width="500" height="400" src="..." alt="...">
<iframe width="600" height="400" src="..."></iframe>
<svg width="20" height="20"></svg>

<!-- not valid, doesn't work, not a good idea -->
<div width="40" height="40"></div>
<span width="100" height="10"></span>

Those attributes are sometimes referred to as presentational attributes. The thing to know about them is that they are overridden by any other styling information whatsoever. That makes them ideal as a fallback.

So, if CSS loads and has a declaration like:

img {
  width: 400px;
}

…that is going to override the width="500" on the <img> tag above. Presentational attributes are the weakest kind of styling, so they are overridden by any CSS, even selectors with very low specificity.

What might be a smidge confusing is that presentational attributes seem like they would have high specificity. These inline styles, for instance, are very strong:

<img style="width: 500px; height: 400px;" src="..." alt="...">

Using an inline style (which works on any element, not a select few), we’ve moved from the weakest way to apply width and height to one of the strongest. Regular CSS will not override this, with a selector of any specificity strength. If we need to override them from CSS, we’ll need !important rules.

img {
  width: 400px !important;
}

To reiterate, presentational attributes on elements that accept them (e.g. <img>, <iframe>, <canvas>, <svg>, <video>) are a good idea. They are fallback sizing and sizing information as the page is loading. They are particularly useful on <svg>, which may size themselves enormously in an awkward way if they have a viewBox and lack width and height attributes. Browsers even do special magic with images, where the width and height are used to reserve the correct aspect-ratio derived space in a situation with fluid images, which is great for a smooth page loading experience.

But presentational attributes are also weak and are usually overridden in the CSS.

The post What’s the Difference Between Width/Height in CSS and Width/Height HTML attributes? appeared first on CSS-Tricks.

Min and Max Width/Height in CSS

Post pobrano z: Min and Max Width/Height in CSS

Here’s a nice deep dive into min-width / min-height / max-width / max-height from Ahmad Shadeed. I like how Ahmad applies the properties to real-world design situations in addition to explaining how it works. In the very first demo, for example, he shows a button where min-width is used as a method for (trying to) make sure a button has space on its sides. It works if the text is short enough, and fails when the text is longer. That’s the kind of „CSS thinking” that is fundamental to this trade.

Direct Link to ArticlePermalink

The post Min and Max Width/Height in CSS appeared first on CSS-Tricks.

Eleventy Love

Post pobrano z: Eleventy Love

Been seeing a lot of Eleventy action lately. It’s a smaller player in the world of static site generators, but I think it’s got huge potential because of how simple it is, yet does about anything you’d need it to do. It’s Just JavaScript™.

The post Eleventy Love appeared first on CSS-Tricks.

Autumn (macOS window manager)

Post pobrano z: Autumn (macOS window manager)

I love how nerdy this is. Autumn allows you to write JavaScript to control your windows. Get this window, move it over here. Nudge this window over. There are all sorts of APIs, like keyboard command helpers and doing things on events, like waking up from sleep.

I love that it exists, but for the moment, my window management mostly consists of: grab this window and chuck it on the left half of the screen, and grab this window and chuck it on the right half of the screen. That and just a handful of other simple things are handled really nicely by Moom.

Doing life tasks with JavaScript is only gonna get bigger and bigger. I love controlling and querying Spotify with GraphQL.

Direct Link to ArticlePermalink

The post Autumn (macOS window manager) appeared first on CSS-Tricks.