CSS @speed
Queries
A theoretical CSS query type for querying connection speed
One thing I feel that’s missing in CSS is knowing how fast a connection is. When we talk about connection speed, we’re usually referring to three things:
- Latency: The time it takes for requests to reach the server, and for the server to respond to them with content.
- Throughput: How fast your connection can receive and send data.
-
Protocol: The current protocol being used. Could be
h1
,h2,
. A value ofh2
could be all encompassing for SPDY and QUIC (though SPDY is deprecated now.)
These all influence how fast websites load for us. What if we could query aspects of this in CSS? Let’s take a look at some quick use cases.
Querying latency
What if we could query connection latency? Here’s example of a theoretical min-latency
media query:
/* Loading a retina image */
@media (min-resolution: 2dppx), (min-resolution: 192dpi), (-webkit-min-device-pixel-ratio: 2){
.masthead{
background: url("masthead-2x.jpg");
}
}
/* Querying a slow RTT */
@speed (min-latency: 200ms){
.masthead{
background: url("masthead.jpg");
}
}
Of course, you could always have a max-latency
rule that would allow you do the inverse of this, but this feels a bit more intuitive to me, at least. The idea is that in high latency environments, the user agent could decide to sacrifice quality for high-DPI screens and download the smaller image.
Querying throughput
Latency isn’t the only environmental pressure on performance (though it is very important). Throughput matters, too. What if we had a max-downstream
property we could query?
/* Loading a retina image */
@media (min-resolution: 2dppx), (min-resolution: 192dpi), (-webkit-min-device-pixel-ratio: 2){
.masthead{
background: url("masthead-2x.jpg");
}
}
/* Querying a slow connection (in Kbps) */
@speed (max-downstream: 10000){
.masthead{
background: url("masthead.jpg");
}
}
In the above example, masthead-2x.jpg
would only download if the connection downstream was greater than 10 megabits. You could theoretically have a related upstream property, or min-
variations of each, of course. You could use throughput and latency querying together:
/* Querying for either high latency or a slow connection */
@speed (min-latency: 200ms), (max-downstream: 10000){
.masthead{
background: url("masthead.jpg");
}
}
Here we’re querying for either a high latency scenario or a connection with a low download speed. If either scenario occurs, the lower quality image would be transferred. You could use the and
keyword to query for both conditions, but that would be far less flexible.
Querying the protocol version
This one is probably strays into the realm of esoterica, but it’s something I’ve done some writing on. HTTP/2 is great, but there’s a lot of browsers out there that may not support it, and some browsers like Opera Mini haven’t signaled their intent to implement support. When these users visit HTTP/2-capable web servers, the connection downgrades to HTTP/1. Since HTTP/2-specific optimization practices encourage less bundling/concatenation of files, this unduly increases the number of requests specifically for users that would be most affected by them. The size of this audience could be larger than you think.
So what if we had a protocol
value we could query?
/* Serve individual icons by default (assuming the web server is HTTP/2) */
.icon.github{
background: url("github-icon.svg");
}
.icon.email{
background: url("email-icon.svg");
}
.icon.twitter{
background: url("twitter-icon.svg");
}
/* Serve an image sprite if the protocol has downgraded to HTTP/1 */
@speed (protocol: h1){
.icon.github,
.icon.email,
.icon.twitter{
background: url("sprite.svg");
}
.icon.github{
background-position: 0 0;
}
.icon.email{
background-position: -2rem -2rem;
}
.icon.twitter{
background-position: -4rem -4rem;
}
}
protocol
would probably be going too far, but could still be quite useful.
Why not just do this in JavaScript?
I have yet to speak authoritatively on the resource timing API, but I imagine one could tag the html
element with a class in some of these instances, but the problem with this is that not everyone has access to JavaScript in all scenarios. Speed queries would admittedly reduce the scope of what could be controlled to only CSS, but the syntax would feel familiar and allow us enough control to change how we serve assets in different scenarios.
Questions? Feedback? Scorn?
Reply below. I have this mirrored at a Github repo as well.