The Magic of Feature Queries, Part 1 – 5/7 Resilient CSS


– I talked in earlier
videos about using the fact that CSS ignores anything
it doesn’t understand and using the way in which
CSS overrides earlier code in the flow to our advantage. To make it so that all of our CSS works in every browser no matter
how well it’s supported, the new stuff is supported. There’s another tool
that we’re going to use, especially going forward into the future, called a feature query. Let’s look at an example of
when and why we would want to use a feature query, why the first two ways of doing
things just aren’t enough. Here let’s look up
initial-letter on CanIUse. We can see that it, in fact, is not very well supported at all. It’s in Safari, which is cool. It’s not the finished version, the whole spec has not
been implemented yet, but an early draft is behind
a webkit prefix in Safari which means all of IOS,
12% of the market according to this screenshot here. We could use this feature. Let’s see what happens. Initial-letter is a great
way to make an enlarged cap, a dropped cap, a raised cap. We’ve been trying to do
it in many other fashions, by using the first letter pseudo-element to isolate the first
letter in a paragraph, and then apply some stuff to it. Typically, we would apply a
float and a huge font size, but the problem with doing it that way, the pseudo-element works fine. You can grab the letter, but you can’t really
control whether or not that letter lines up with
the text that’s there. Maybe you go into one browser
and you make the letter 2.4em, no 2.6em, no 2.539em, perfect! Oh, it lines up with three lines of text. Looks great, but then you
open it in another browser and it’s like off by just a little bit, because the browser’s not
completely consistent. Initial-letter is a property
that’s going to solve that problem for us and it’s
going to allow us to say, hey, browser, I want
you to take this letter and I want you to make it the
size of four lines of text. You figure out the math, you figure out how big it should be, you figure out the layout. You know it’s going to be a big letter, just make it the size
of four lines of text. Works much better than
the techniques we’ve tried to use in the past. Here I’ve got, I’m isolating this giant L with the first-letter pseudo-element, I’m going to apply a colour to it to make it kind of a
pale orange-pinky colour. Let’s make it bold. Put a little bit of right margin on it, so that it’s not touching
the text that comes after it, and we’ll put the property
here, initial-letter: 4. We also need -webkit-initial-letter: 4, because it is behind the prefix. It works great in Safari. You can see the screenshot
of how awesome it looks. Let’s look at another browser. What’s going to happen? Well, initial-letter is not understood, so that doesn’t get applied. Okay, that’s fine. Oh, but the colour,
the font-weight of bold and the margin is going to get applied. You end up with this little,
tiny L that’s super white and has this awkward space after it. That is not going to work. We can’t ship it like
this to 88% of our users, so what are we going to do? Well, what we’re going to do is
we’re going to wrap this code in what’s called a feature query where you say @supports
(initial-letter: 4). It’s a conditional. It’s basically saying, hey,
I’ve got a bunch of code, but I only want you to run this code if you support this property and value. If you, browser, support
initial-letter: 4, then please run this code. If you don’t understand this property, I want you to skip this
entire block of code. It’s a lot like a media query, where a media query says, hey, if the browser window is
wider than this amount, then run this code. If it’s not, then skip this code, right? It’s the same kind of
structure as a media query. It works very similar, it’s written in the same
syntax as a media query. Great!
So now, we wrap this code in a feature query and we get these two experiences. You can see on the top
where all the browsers that don’t support initial-letter
are going to have nothing, and the browsers that do
support initial-letter are going to have a giant L. Which means we can ship this today, we can use it today on
websites without a problem. As more and more browsers start
supporting initial-letter, the more and more browsers will start to get this little graphic design tweak. It’s called a feature query. The syntax looks like this, as I’ve said, @supports (foo: value). You do need both the
property and the value with a colon between. You can’t just have half,
you need the whole statement, and you put your code inside. This is the kind of thing that
we’re going to use very heavily as we start to use CSS Grid. You’re going to write
some sort of a layout that’s going to work in all browsers, including the browsers that
don’t support CSS Grid. Then, you’re going to say,
@supports (display: grid) { and you’re going to put in
code that is going to run only in the browsers that support Grid, including the code that uses Grid and usually a little bit of code maybe to override some of the
things that you did above. Maybe reset some widths to
auto, maybe remove some margins that you don’t need anymore. I did that here with this
example of a Grid layout. We can see this running in
Firefox probably right now. It works in any browser that has Grid. This is how it’s going to
look in ideal situations. When we have no CSS at all, this is what we get. The very first thing that I do is figure out my source order. Figure out what should the content be if there were no CSS at all. The logo’s going to go to the top, then Jazz at Lincoln Centre, the Spring 2017, then the
words “Schedule of Events,” if you look at this example you’ll see that Schedule of Events
doesn’t exist anywhere on the page visually. It only exists in the markup, but this is great for anyone
using a screen-reader, anyone who’s using something
like Instapaper or Readability or a Read-It-Later button, Reader modes, people are using these tools more and more and more in browsers. We actually don’t even have any stats as to how many people
either save the article or the page to be looked
at in an app later on, or how many people use a
button like Reader mode to kind of strip off the CSS. We have no idea. That could be a really, actually
a really large percentage of our audience, but tools like Google
Analytics don’t measure that so we don’t know. You want to make sure that
your HTML is really solid, your source order is really
solid so you can redesign later. If Cortana or Siri or
Alexa wakes up one day and starts reading webpages aloud, that your site is going to be
ready for that eventuality. Also, I’ve got a view, a way that it looks when there’s no support for
Grid, but CSS is applied. This layout is fairly basic. It’s just kind of a float-based
layout that I created. Nothing fancy, but for this use, case it actually kind of makes sense. This sort of float drop
problem that we see here that we’ve actually been
trying to avoid for years. Since it’s Jazz, it kind
of has this feeling. That actually works pretty well. Here’s the code for this. You can see that I start
with my basic layout for non-supporting browsers
where I am, in fact, floating my list items. I have some width set to things, and then I have an
@supports (display: grid) { where I take off some of
the code that I don’t need when I’m using Grid, and then
I start writing all the code that I do need for Grid. It’s not a lot of code to
do the fallback layout. It’s only 16 lines of CSS,
it didn’t take a lot of time. It just took a bit of thinking
through what’s going to happen. It’s not twice as much work as one layout, it is way in which we can use Grid today, even though 100% of our
users don’t have it yet. So, there it is, @supports
(display: grid) {, put all of your new code in there. There’s a couple ways we can write these, the syntax of them. Here @supports (display: contents) {, so for example, you might be wondering, well, initial-letter: 4, do I
really need that number four? The four isn’t really important. The fact that you have both the property and the value is important,
(display: contents), because every browser understands display, not every browser understands contents. That’s why we need both. Very simple statement
here in this example. In the next example, you can see I’ve said (initial-letter: 1) or
(-webkit-initial-letter: 1). You can have an or statement. If one or the other one is true, then the code will run. In this case, it’s pretty
important because of the prefix. We need to test for both cases,
not just one or the other, but both of them and
then let the browser do what it should be. Or here, I could say, hey,
I’m going to run this code if you understand (display: grid) and you understand (display: contents), then go ahead and run this code. If you don’t understand
(display: contents), then I don’t want you to run
any of the rest of it either. There’s a one more way that
you can structure your code @supports not (display: grid) {. I’m going to talk in the next video why this is probably a really
bad idea to do it this way, at least for the next several years. I avoid using the not
statement most of the time. It’s tempting, but it’s not a good idea, and like I said, I’ll
explain that in a minute. Feature queries, very
powerful tool for us to use while we’re writing code
that’s going to work in every browser no matter
how old that browser might be.

Add a Comment

Your email address will not be published. Required fields are marked *