Blog posts from 2013
-
Playing around with CSS variables - "custom properties"
Edit 2015-03-29: I've updated this post to reflect the new syntax from the spec.
To begin with, the name CSS variables is only partly correct. They are variables of a sort, but the correct name, and way of looking at it, is custom properties. The full name of the specification is "CSS Custom Properties for Cascading Variables". I have a hunch that the "Cascading Variables" part of the name is what makes it really interesting.
The basics
Let’s jump into some introductory examples. To create a custom property, you simply declare it, and make sure it begins with
--
, think of it as being likedata-
attributes on HTML elements – as long as it starts with a double dash (and is syntactically valid as a name), it's valid. The value can be any valid value for CSS. So to create a custom property (or variable, if you wish) that we can use anywhere in our document, we declare it using the:root
selector::root { --primary-color: firebrick; /* yes, that is a valid color keyword. pret-ty cool. */ }
To use this variable somewhere else, you can reference it with the
var()
function notation, passing in the property name. The second argument to the function is the fallback value, in case the custom property is not declared on an ancestor (and thus inherited) or invalid:.myComponent { color: var(--primary-color, #000); }
Using the cascade as variable scope
Declaring a custom property only on a specific selector means that it’s only reachable within the context of that selector, since it’s automatically inherited. Combining this with the fact that using custom properties can have fallback values, we can decouple specific styling from selectors, and couple them to the context of the variable instead.
One example that pops up in my head is when we have a part of a page that comes from a CMS, like a blog post: in that case, we might want to apply some sort of base styling that we don’t really use outside heavily of this context. The goal is to make the HTML inside of this block behave consistently, and not let that affect the rest of the page (which might be more "UI" than "content", if you get what I mean). I usually have some sort of classname, like
.flow
, that I use in these cases, and then style descendant selectors..flow p, .flow h2, .flow h3, .flow h4, .flow ul { /* Properties for nice consistent flow here */ }
Now, say that this styling relies on some sort of vertical rythm, sort of like Harry Roberts’ idea of single-direction margin directions. We can create a context where this is applied to descendants of the
.flow
class without really tying it to the selector itself, but instead tying it to the base styling of the elements themselves. An example to explain:.flow { /* set the var-flow-space custom property on elements inside .flow */ --flow-space: 1.375rem; } h2, h3, h4, h5, ul, p { /* If the var-flow-space is defined, apply that for margin bottom, otherwise 0 */ margin: 0 0 var(--flow-space, 0) 0 ; } }
This means that outside of the “flow” context, elements are normalized to have no margin, except
margin-bottom
if the--flow-space
property is inherited. We could, if we wish, define other contexts where we want to use a consistent margin-value for these elements, e.g. small-print: we just make sure to redefine the variable inside a selector that we use for that context.Going further: goodies from the spec
One of the first things that I tried (without reading up on wether it was possible or not) was to concatenate/interpolate other property values with the
var()
notation, likevar(--my-val)px
. This does not work. However, the spec mentions this case explicitly, and gives us a brilliant use of thecalc()
function to make this happen. We can simply create the units we want by operating on them::root { /* unitless number */ --vertical-base: 1.375; } .flow { /* use the number to set context-specific base number */ --flow-space: var(--vertical-base); } h2, h3, h4, h5, ul, ol, p, blockquote { /* Normalize, use calc to give the flow-space (if set) variable a unit */ margin: 0 0 calc(var(--flow-space, 0) * 1rem) 0; } blockquote { /* give blockquotes inside contexts where flow-space is set a consistent side padding */ padding: 0 calc(var(--flow-space, 0) * .5rem); }
Setting custom properties to read from scripts
Another thing that the spec mentions explicitly is setting custom properties to be read by JavaScript. This ties in nicely with the idea of not having breakpoints duplicated in both CSS and JavaScript, like what Jeremy outlined in “Conditional CSS” and that I (and others) proposed a solution to via using the <code>content</code> property alongside <code>getComputedStyle</code>.
Sadly, it does not seem possible to use custom property values inside media queries, like
screen and (min-width: var(--lapsize))
, which would possibly make authoring of media queries a bit more DRY. It is, however, fully valid to set variable values inside media queries, so we could do something like this:/* Yes, I know the category names are convoluted, but man, these things are hard. */ @media screen and (min-width: 25em) { :root { --screen-category: small-lap; } } @media screen and (min-width: 48em) { :root { --screen-category: lap; } } @media screen and (min-width: 80em) { :root { --screen-category: desk; } }
Then we can read these values by using the new JS API to get the value of custom properties, using something like this on resize etc:
var screenCategory = el.style.var.get(‘screen-category’);
This is not implemented in the Firefox Nightly, so I haven’t been able to play around with it yet. Edit: It seems this interface has been postponed in general, so it's not available yet.
I’ve put up the very quick-n-dirty source code for my experiments on JSBin. Download the nightly, play away!
Like I said in the beginning of the article, it’ll probably be a while before this is in all major browsers, and using it properly without massive fallbacks (thus negating the need for it) would be hard. I’m not sure how hard or easy it would be to polyfill in some way (probably hard), but for now it’s just massively fun to play with and try to figure out how to use once it’s there.
Read the whole post "Playing around with CSS variables - "custom properties""
-
Sticky footers, flexbox and IE10
I recently came across Philip Walton's excellent ”Solved by Flexbox” site, where he shows some good examples of using flexbox to create common layout patterns, some of which have been really tricky to solve with CSS until now. Since there's multiple versions of the flexbox syntax, the examples on Philip's site are (quite sensibly) only focusing on the latest, more stable version. When I tried out the example for ”sticky footer” with all of the different versions of the flexbox syntax, I found that it didn't work in IE10. This post explores how to fix that, as well as make it work in all other browsers that support old and new flexbox syntax.
-
Webmentioning Adactio
Jeremy has recently implemented Webmention on adactio.com, and posted an explanation of the small piece of code involved. I I love the simplicity of Webmention, and I love the Indieweb idea of connecting our conversations in the simplest possible way whilst still publishing to our own sites, owning our data. I intend to implement it on this site as soon as I can: both to test it out, and to offer a way of commenting without all the hassle of actually managing comments (sort of).\r\n\r\nI do have one teensy tiny criticism though: what's that little bit of tech-specific junk doing in the Webmention URL, Jeremy? ”Dot PHP”? Cool URI:s don't change, but publishing platforms and script languages do, right? Excuse me sir, your CMS is showing! :-)
-
My Metaphorical Job Title
I'm a web developer. At least that's what it says on my business card. If I have to be specific, I'm a front-end web developer. In practice, I do a lot of things that are not developer-y, and sometimes drift more towards a role that's probably normally labelled ”designer” of some sort. When people ask, I mostly try to say ”I build websites”. But behind that, what kind of developer am I really?
-
Progressive Enhancement: Still Not Dead.
There's been a lot of focus on Javascript the last couple of years. Sometimes, the best way of building a web property is described as just slapping a JS-driven app on top of a REST-API, and I have some issues with that. More specifically, I think the benefits of progressive enhancement are still misunderstood, and progressive enhancement is Still Not Dead. Layering support for user-agents, performance and being robust against broken or blocked JS code are very good reasons.
Read the whole post "Progressive Enhancement: Still Not Dead."
-
Viewport relative unit strangeness in iOS 6.
Using the new viewport-relative units in CSS3 is compelling when creating flexible layouts across different screensizes. It is early days though, and it turns out there are some issues in browser implementations that are worse than others–and iOS 6 is a doozy in this regard. This post explores what I think is the cause of its weirdness.
Read the whole post "Viewport relative unit strangeness in iOS 6."
-
Drowning
In which I have a bit of a Billy Joel moment. Tools, technologies, frameworks, methodologies, buzzwords, services... Sometimes I just get very, very tired.
-
On the value of testing on real devices
There's sort of this saying in the UX disciplines, that you never really know what you will learn when you do usability testing with real humans, but you will always learn something new every time you actually put the thing you're working on in someone else's hands. I can attest that yes, you do learn something every time, and you should try it. What I've found is that pretty much the same thing is true for doing varied device testing.
Read the whole post "On the value of testing on real devices"
-
Wrangling white-space
Some quick notes on problems with white-space and line-breaks in source-code not cooperating with the intended output, and how to deal with it, now and in the future.
-
About donating blood
Today I donated blood for the first time. I’ve been meaning to do that for a long time, but following the normal course of yak-shaving/bikeshedding etc, there was always some excuse for not doing it "now"—needing more info, not wanting to be tired ahead of some important activity, not knowing when the donation bus was going to be around etc etc. For some people, the idea of getting stung by a rather large needle might also be an issue.
I have a very rare bloodtype, where the plasma in my blood can be used for receivers with any blood type, so I’ve understood that my blood is really, really valuable for the people working every day to save lives. And from what I gather, they normally don’t have enough of any blood type. So the stuff spinning around in your head before making a decision to donate blood is keeping you from doing a very simple thing that is hugely important and helpful.
Here’s a list of stuff you should check right now, to go from maybe thinking about it but not doing it:
- There’s probably a site with most of the info you need about how it works in your country and/or city. Here in Sweden it’s geblod.nu. Go there, read up.
- There are very strict regulations about who can give blood: diseases, medication, medical history, travel habits, tattoos etc—all these things can be possible reasons why you cant give blood. Read up on them now: maybe you’re not even eligible to donate, and you can put this out of your mind for a while.
- Here, there are blood buses that go around various parts of town, and you can sign up for notifications when they’re in your area. If you think you are eligible to donate, do that, and at the nearest possible occasion, go and do the initial testing, it takes half an hour or so.
- It doesn’t hurt. Seriously, it’s a tiny needle sting. It’s not even close to like stepping on a lego piece. It’s a pretty big needle, but if that bums you out, just don’t look at it.
- You’ll be fine after donating, just maybe a little bit tired for a while. I can’t really tell the difference. I expected to be really tired and weak—not so. The advice is to not do physical excercise the same day, but you will not be completely out for the day, far from it. Of course, I’m not a doctor and your mileage may vary, etc.
So there. It’s not a big thing, it’s simple. Read up on if you can donate, get yourself tested, donate.
-
Hello
There's a lot of things that can stop you from getting your own site or blog off the ground, mainly fear of failure and too much tinkering.\r\n\r\nThis is the inaugural post, about how a tweet over a year ago got me agonizing over finally getting this thing out the door.