WarnerMedia’s new streaming service HBO Max launched today with couple of conspicuous absences from the list of supported devices — Max is not yet available on Roku or Amazon’s Fire TV.
It sounds like this isn’t just a technical issue that will be fixed imminently. WarnerMedia’s vice president of communications Chris Willard told USA Today that “there is no deal in place” to bring the service to those platforms.
In a statement sent out this afternoon, Amazon suggested that the disagreement revolves around bringing HBO Max to Prime Video Channels, and around HBO’s somewhat confusing distribution strategy. (For those of you who haven’t been following along: The HBO Now app is being updated as HBO Max, which includes HBO, plus a bunch of other content. At the same time, HBO will continue to operate as a standalone brand.)
The company said that by not making Max available through Prime Video Channels, WarnerMedia’s parent company AT&T “is choosing to deny those loyal HBO customers access to the expanded catalog.”
Here’s Amazon’s full statement:
With a seamless customer experience, nearly 5 million HBO streamers currently access their subscription through Amazon’s Prime Video Channels. Unfortunately, with the launch of HBO Max, AT&T is choosing to deny these loyal HBO customers access to the expanded catalog. We believe that if you’re paying for HBO, you’re entitled to the new programming through the method you’re already using. That’s just good customer service and that’s a priority for us.
Meanwhile, a statement from Roku also pointed to unresolved issues:
As the No. 1 streaming platform in the U.S. we believe that HBO Max would benefit greatly from the scale and content marketing capabilities available with distribution on our platform. We are focused on mutually positive distribution agreements with all new OTT services that will deliver a quality user experience to viewers in the more than 40 million households that choose Roku to access their favorite programs and discover new content. Unfortunately we haven’t reached agreement yet with HBOMax. While not on our platform today, we look forward to helping HBOMax in the future successfully scale their streaming business.
CSS was introduced to the web all the way back in 1996. At the time, most computer monitors were pretty terrible. The colors of CSS — whether defined with the RGB, HSL, or hexadecimal format — catered to the monitors of the time, all within the sRGB colorspace.
Most newer devices have a wide-gamut display. A gamut is the range of colors that can be displayed. A wide-gamut display is capable of showing more colors than sRGB. They use the Display P3 colorspace. (There’s also Rec.2020, an even larger colorspace, but that’s pretty rare and not currently worth thinking about.) As Lea Verou of the CSS working group put it, “Our websites are washed out because screens advanced faster than CSS Color did.” If we want to make full use of the range of colors that the majority of screens are capable of displaying, we need to use new CSS colors formats: lab, lch or display-p3.
Examples in the wild can be found on the website of Panic (creators of the once popular Coda text editor and the still very popular Untitled Goose Game) or the marketing site for a product called Playdate. They both make use of strikingly vibrant and intense colors that are uniquely vivid by making use of display-p3.
To get some idea of the range of colors that are missing from sRGB, check out the following Pen. The inner boxes contain a color beyond the sRGB gamut. The outer boxes show that color clamped to the sRGB color gamut (meaning the nearest equivalent color that a browser is capable of showing without using display-p3, lab, or lch). (Note that support is currently limited to Safari users.)
The color picker in Safari Technology Preview helpfully shows which colors lie outside of the sRGB color gamut.
Any color above or to the right of the white line lie outside of the sRGB gamut
A tale of new syntaxes
Before jumping into the syntax for lab(), lch(), and the color() function, let’s take a look at the new rgb() and hsl() syntaxes (which are supported in all web browsers, minus Internet Explorer).
In the older syntax, each number is comma separated: rgb(200, 100, 20);. Commas are no longer necessary, so the space separated value rgb(200 100 20); is valid. To specify transparency, we can now use rgb(200 100 20 / 50%) rather than using rgba() or hsla(). There’s no real benefit to the newer syntaxes but it’s worth looking at because they match the syntax for lch(), lab() and color().
lab(), lch() and color() always use space separated numbers (no commas allowed) and a forward slash followed by a percentage to specify transparency. Let’s take a look at how they work.
The CSS color() function and display-p3 colorspace
The color() function allows a color to be specified in a particular colorspace (rather than using the sRGB colorspace used by rgb(), hsl(), or hex). The colorspace we need to specify in order to use wide-gamut color is display-p3, which uses three numeric values, representing the red, green, and blue channels of the color: 1 0 0 is total red, 0 0 1 is total blue, and 0 1 0 is total green.
background-color: color(display-p3 1 0 0.331); /* vibrant pink color */
At the time of writing, display-p3 is the only way to access high-gamut colors, having been supported in Safari since 2017. However, lab() and lch() will be better options once they are implemented (Chrome and Safari are currently working on it). Here’s a take from Lea Verou:
display-p3 is not perceptually uniform, and is difficult to create variants (lighter or darker, more or less vivid etc) by tweaking its parameters. Furthermore, it’s a short-term solution. It works now, because screens that can display a wider gamut than P3 are rare. Once hardware advances again, color(display-p3 ...) will have the same problem as sRGB colors have today. LCH and Lab are device independent, and can represent the entire gamut of human vision so they will work regardless of how hardware advances.
A better lightness: Lab and LCH
You may have seen articles around the web arguing that HSL is easier to reason about than RGB or Hexadecimal values.
The real appeal of HSLa is that it makes more intuitive sense what changing the values will do to the color. Increasing the second value will increase the saturation of that color. Decreasing the third value will decrease the lightness of that color. That makes creating your own color variations on the fly way easier.
While HSL might be easier to understand than hexadecimal or RGB, it’s far from perfect. The way it calculates lightness simply doesn’t match human perception. According to HSL, hsl(240deg 100% 50%) and hsl(60deg 100% 50%) have the same lightness, 50%. Let’s compare the two.
To the human eye, the blue looks darker. As Brian Kardell puts it:
Doing things like mixing colors, lightening, darkening, can be done well only if they include a sense of how our eyes really work rather than how machines like to think about storing and displaying.
A trick for aesthetically pleasing gradients of the same color at different lightnesses is to convert to Lab, vary the L instead, and then convert back to HSL/RGB.
“The perceived brightness of all of the hues in a spectrum with the same saturation and lightness. […] It’s quite clear they’re different.” —Brian Kardell (Image: Rob Waychert)
Lab and LCH both use the CIELAB colorspace which is designed to align with human vision. If you give two colors the same lightness value, they appear to the human eye to have the same lightness, regardless of their hue.
Lab
background-color: lab(40% 83 -104); /* a shade of purple */
The L in lab() stands for lightness and is written as a percentage (which can go up to 400% for extra bright white, but will generally be between 0% and 100% ). A and B don’t stand for anything — they’re color channels. A is a numerical value between green (negative values) and red (positive values) while B is a numerical value between blue (negative values) and yellow (positive values). Lightness is pretty easy for us to understand. The red/green value and blue/yellow value, however, aren’t exactly intuitive. LCH is probably a better alternative.
LCH
background-color: lch(69% 56 244); /* a shade of blue */
lch() is the most human-readable of the new color values. L again stand for lightness (and works in exactly the same way), C is for chroma, and H is for hue. Chroma is largely analogous to saturation, but it can also be thought of as the color intensity or vibrancy. Unlike the other new color formats, you can actually predict the sort of effect changing these individual values will have — its similar to HSL in this way. The best way to get your head around it is to try out this LCH color picker.
Defining fallbacks
We have two kinds of support to think about: browser support for the new CSS color values and the ability of screens to display these colors.
Falling back to the closest matching sRGB value for browsers that don’t support color functions is easy and exactly like we’re used to defining fallback properties:
.pink-text {
color: rgb(255, 0, 79); /* Will be used as a fallback */
color: color(display-p3 1 0 0.331); /* Will be used if supported */
}
The second line of code in the example above will be ignored if the browser doesn’t understand it and the rgb() value will be used instead, thanks to the cascade. It would be laborious to type out two lines of CSS every time you want to specify a color. CSS variables are a great way to deal with this. In this example we’ll use @supports to tell if the browser has support for color functions in CSS:
There is a PostCSS plugin that converts lab() and lch() functions to rgb(). If you’re into Sass there is a tool from Miriam Suzanne called Blend.
A media query for color
@supports tells us whether the browser supports the relevant CSS syntax. What it doesn’t tell us is whether a user’s monitor can actually display certain color values. If a monitor doesn’t support high-gamut color, the screen will display the nearest equivalent sRGB color. This means all monitors are catered for without writing any extra code.
However, if you’d rather choose the fallback color manually yourself rather than let the browser calculate one for you, you can pass a second color value to the color() function. This would, however, require browser support for the color function (but support for the second argument hasn’t landed in any browser yet).
Should you need greater control to do something fancy, the Media Queries Level 4 spec brings a new color-gamut media query that can help us here.
@media (color-gamut: p3) {
/* Code to run only on hardware that supports P3 color */
}
In this example, we are obviously checking for P3 support, but we could also check for the rec-2020 colorspace we alluded to earlier, which has an even wider gamut than P3. The number of screens supporting rec-2020 is currently minimal and only include high-definition televisions, meaning they won’t be a common target for developers in the near future. You can also check for sRGB support, but that is almost all monitors nowadays. The color-gamut query, on the other hand, has reasonably good browser support at the time of writing.
Sidenote: dynamic-range media query
In the Safari 13.1 release notes, the dynamic-range media query is is used to conditionally apply a P3 color. Apparently, that’s not a good use case. According to Florian Rivoal (editor of the Media Queries specification), this query is designed to be used for video:
[S]ome screen can show ultra-bright lights for brief amounts of times, that are used in videos for things like sparks, direct sunlight, etc. This is much brighter than white, and isn’t meant to be used with static images. It would be uncomfortable, and would also damage the screen.
One more sidenote: Design tool support
Unfortunately popular web design tools like Figma, Sketch and XD do not currently support Lab, LCH or P3 colorspaces. Photoshop, however, does have a Lab color picker.
There we have it! CSS colors are expanding at a time when screens support more colors than ever. It’s an exciting time for color nerds out there!
Manuel Matuzović details 10 bad HTML patterns for a close button. You know, stuff like this:
<a class="close" onclick="close()">×</a>
Why is that bad? There is no href there, so it really isn’t a link (close buttons aren’t links). Not to mention the missing href makes this “placeholder link” unfocusable. Plus, that symbol will be read as “multiplication” or “times”, which is not helpful (an “x” isn’t either).
What do you use instead?
There are plenty of good patterns too. If you prefer the visual look of a ×, then…
Today at Jamstack_Conf, Netlify announced Build Plugins. What it does is allow you to have particular hooks for events within your build, like when the build starts or ends. What’s nice about them is that they’re just a plain ‘ol JavaScript object, so you can insert some logic or kick off a library just the way you typically would within your application.
A “Build” is when you give your site to Netlify either via GitHub/GitLab/etc., or by literally just dropping the directory into the interface, Netlify will process all the assets, download and install packages, and generate a static version of the site to deploy to CDNs all around the world.
What the Build Plugin does is give you access to key points in time during that process, for instance, onPreBuild, onPostBuild, onSuccess, and so forth. You can execute some logic at those specific points in time, like this:
module.exports = {
onPreBuild: () => {
console.log('Hello world from onPreBuild event!')
},
}
You don’t only have to build them yourself, either! You can use build plugins that have been made by the community. There are very interesting ones, such as a11y, Cypress for testing, Inline Critical CSS, and my personal favorite, Subfont, which optimizes fonts for you in a really incredible way (you can watch a video about that).
Enable them through the dashboard through a few button clicks:
Ethan on the thinking and research that inspired the term:
Around that time, my partner Elizabeth visited the High Line in New York City shortly after it opened. When she got back, she told me about these wheeled lounge chairs she saw in one section, and how people would move them apart for a bit of solitude, or push a few chairs together to sit closer to friends. We got to excitedly chatting about them. I thought there was something really compelling about that image: a space that could be controlled, reshaped, and redesigned by the people who moved through it.
I remember spending that evening reading more about those chairs and, from there, about more dynamic forms of architecture. I read about concepts for walls built with tensile materials and embedded sensors, and how those walls could bend and flex as people drew near to them. I read about glass walls that could become opaque at the flip of a switch, or when movement was detected. I even bought a rather wonderful book on the subject, Interactive Architecture, which described these new spaces as “a conversation” between physical objects or spaces, and the people who interacted with them.
After a few days of research, I found some articles that alternated between two different terms for the same concept. They’d call it interactive architecture, sure, but then they’d refer to it with a different name: responsive architecture.
Fascinating.
Responsive web design is so locked in now a decade later it’s just an assumption. I would have called it an assumption in half that time. My answer in an interview…
Is responsive something that you have to sell in any more or does everyone get it now?
I think that responsive design was an assumption in 2015. Even then, if you delivered a website to a client that was just a zoomed out “desktop” website they would assume it’s broken and that you didn’t really do your job. Today, even more so. It’s just not done.
The technical side of responsive design is fascinating to me of course. Even Google has guides on the subject and highly encourages this approach. But the core technical implementation isn’t particularly complex. Stay fluid; use some @media queries to restyle things as needed.
The bigger deal in the last decade was the impact on businesses. Adjusting workflows to accommodate this style of thinking. Combining teams of developers who used to work on entirely different codebases now working on a single codebase. The impact at organizations wasn’t nearly as straightforward as the technology of it all.
There is a resonance between that and more recent shifts in the world of building websites, like the astounding rise of design systems and, even more so, the Coup d’état of JavaScript.