One of the things I recognize at Google is how productive developers surround themselves with powerful tools for iterative development and debugging. For us front-end developers, the ecosystem of tools has exploded in the past two years, as we have a lot more software and libraries beyond Firebug and jQuery to help us build webapps. In the talk below I walk through the current ecosystem of tools and how they can make your development experience a more enjoyable one.
My slides:
Because there are so many tools around, I wanted to break them down somehow. I think contextualizing the tools as to what phase of development that assist with works well:
(You could think of the Y-axis here as the amount of code in a project..)
Looking at our tools this way we end up with:
Boilerplate
You likely start a project with more than a single blank text file.
Authoring Abstractions
CSS preprocessors, Languages that transpile to JS, Templating
I've been thinking a lot about workflow and integrating these tools together. Screencasts like Andrey Tarantsov's Sublime Text Workflow really excite me and I'm eager to see more people exploring a robust development setup.
The premise of prefixes makes unrealistic demands on how developers maintain sites
There's a lot of conversation about making prefixes work (by changing policy), but I believe they already are at odds with the developer workflow. In this proposal I hope to show that:
prefixes are not developer-friendly
recent features would have been in a much better state without prefixes
implementor maneuverability is not hampered without prefixes
The developer experience
If I'm using a feature that's prefixed, I have a choice of using a tool to help me manage outputting the various prefixes I need or I'll do it myself. Based on myinformal poll last week it looks like 40% of developers are not using tools. Without tool usage, authors are not including-ms-, -o-or the unprefixed variants.Page 4 of Mozilla's prefix report verifies this; developers don't write necessary prefixed properties about half the time (e.g. -o-transform) and in fact, they already write out the unprefixed variant well before the spec goes to CR (and do this well before adding in-ms- or-o- compatibility).
This matches my experience as well. I don't want to return to this code to maintain it, so I'm going to add the unprefixed version. There is less of a cost to me leaving the unprefixed version and assuming I won't need to change it vs. returning to my CSS of shipped-to-production work to add unprefixed variants each time a feature hits CR.
Any successful evangelization plan for prefixes relies on tools, but all tools prioritize the unprefixed state.prefix-free, compass,andcss3 please(I'm a tool vendor, too)all heavily suggest starting with the unprefixed state. So any successful evangelization push will just result in the unprefixed version being 100% deployed from the get-go, which ties implementors hands anyway and defeats the purpose of the prefix. I don't have data to show that developers are not returning to their deployed, production code to update prefixes, but anecdotal evidence suggest so. Opera’s Web Opener team, for example, reports a <10% success rate when directlycontacting sites to request updates to their prefixes.
PPKwrote “If standards make web developers’ lives much harder, web developers ignore standards. This was true back in 1998, it’s still true today.” Without prefixes, implementors have an opportunity to empower developers to do the right thing while still allowing room for innovation.
PPK covered this ground well last week, but in short the policy of binding prefix-drop to CR has failed plenty. Developers have no expectation of when this will happen, nor should they.Mozilla’s roc has confirmeddevelopers are using prefixes and they won't stop regardless of their supposed "experimental" status.
Let’s imagine there were no prefixes
So without prefixes, vendors hands would be tied and the first implementation to ship would be the one to stick, right? Nah. I think we can walk through a few examples from recent history too see what it would have been like if there had been no vendor prefixes in play.
transitions, transforms, animations
While plenty of implementation bugs were fixed, the developer would never have updated their syntax and would have complete browser support.
box-sizing
No problems. No changes.
css-gradients
Gradients has been the most tumultuous css spec, but if they had been implemented without prefixes, the feature would be in a better situation today.
Browsers discard properties and values they don’t parse successfully, so developers would have just included a cascade of the iterations of the spec. This would have successfully targeted all shipped versions of gradients:
.blacktowhite{background-image: gradient(linear,lefttop,leftbottom, from(black), to(white));/* initial webkit proposal */background-image: linear-gradient(top,black,white);/* mozilla proposal */background-image: linear-gradient(to bottom,black,white);/* likely the CR */}
flexbox
Mozilla started Flexbox v1, WebKit followed with a slightly stronger implementation. Both Alex Russell (post) and I (article) recommended boilerplate code that assumed no change for unprefixed state and blocked outIE10’s upcoming implementation.
Flexbox v2 debuted and has an implementation in Chrome. Syntax is already different enough that the fallback story is happy. Without prefixing, the resulting browser support of shipped author code would be better. Again, I see no drawbacks in this example had these properties not been prefixed.
requestAnimationFrame
Soon after this feature debuted,shims were written to manage all prefixed implementations including the unprefixed state. (Sorry). Combined with quick adoption, browser have as much ability to change the feature as they would if it were unprefixed to start (that is, not much ability).
Risks and Resolutions
In CSS, new breaking changes have to introduce syntax changes that would break previous parsing attempts, as seen in the gradients example. However, if the semantics of a feature changed without syntax changes, we’d have a situation where developers are forced to detect each behavior and write compatibility code.
border-image introduced a similar situation recently: WebKit changed its semantics and required a `fill` keyword to match previous behavior. Sounds like trouble, but this change happened when the unprefixed variant was exposed, matching implementor best practices of changing a feature. The result: Greg Rewis of Adobeblogging that Chrome broke his site.
This is truly how it is supposed to work, but still expectations are broken. Developers have plenty of motivation to leave in the unprefixed state at the beginning, but this means that any change will always break them. With prefixes or without prefixes, we would have gotten the same resolution here.
In JavaScript/DOM we have a more secure safety net, as behavior can be detected. Take for examplequerySelectorAll(); it was shipped without prefix and while implementation differences exist, JavaScript libraries detect and route around them. Of course, semantics can change and the prefix → unprefix move provides an opportunity, but in my experience it’s more common to see these changes happen early on (like blob.slice()’s change).
Without prefixes there will be no mechanism to notify developers “beware, thar be dragons!”. Prefixes don’t do this now, as their removal isn’t prioritized so developers accept them as a fact of life rather than an indication of instability. The solution: getting accurate metrics of feature usage and adoption can inform implementors of if it’s too late to change a feature or still early enough to modify.
Yes, but…
As vendor prefixing is a well-worn debate, allows me to deflect common challenges to this proposal to:
The community to evangelize use of tools like Compass that protect authors from bad authoring practices and so folks who publish tutorials don't solely define their -webkit- styles.
Browsers to track feature adoption to inform better decision-making around changes. (Answering the question: Are we stuck?)
This data should be public and update regularly.
Should be based on pageviews, to accurately weigh when a CNN.com implements something
Other browsers to implement a defined set of -webkit- prefixes on their mobile browsers. I don’t see a way around this nor do I think it’s bad.
Drop the notion that evangelism gets us out of this mess. I've been doing this evangelism myself for the past 3 years, but I'm also a realist. This situation needs new policy and (clearly) needs speed out of the CSS WG.
Browsers to clarify afeature detection strategy that it supports. For example, developers have no reliable way of detectingChrome’s 3D transforms support[1,2] or discounting Chrome’s-webkit-hyphensfalse positive[3]. All proposals for handling experimental properties need accurate feature detection techniques to be effective.
In summary, the ideal developer experience is 1) using tools to manage prefixes and 2) always using the unprefixed state to reduce maintenance cost. These two facts eviscerate the benefits that prefixes were introduced for, leaving only the drawbacks.
One of my least favorite parts about layout with CSS is the relationship of width and padding. You're busy defining widths to match your grid or general column proportions, then down the line you start to add in text, which necessitates defining padding for those boxes. And 'lo and behold, you now are subtracting pixels from your original width so the box doesn't expand.
Ugh. If I say the width is 200px, gosh darn it, it's gonna be a 200px wide box even if I have 20px of padding. So as you know, this is NOT how the box model has worked for the past ten years. Wikipedia has a great history of this box model. Jeff Kaufman also dove into the history
Anyway, I have a recommendation for your CSS going forward:
/* apply a natural box layout model to all elements */*{ -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;}
This gives you the box model you want. Applies it to all elements. Turns out many browsers already use border-box for a lot of form elements (which is why inputs and textareas look diff at width:100%;) But applying this to all elements is safe and wise.
Browser support
Due to browser support, this recommendation is only for projects that support IE8 and up. (Full browser compat at MDN) Firefox still needs the -moz- prefix, and <= iOS4, Android <= 2.3 need the -webkit-, but everyone else uses the unprefixed. You can find more info about a box-sizing polyfill for IE6 & 7 at html5please.us/#box-sizing (which was developed with * { box-sizing: border-box!).
Is it safe to use?
Totally. jQuery works pretty great with it (except this). As mentioned, browser support is excellent. And a number of projects use this layout model by default, including the WebKit Web Inspector (aka Chrome DevTools). I heard from Dutch front-end developer Yathura Thorn on his experience:
We've been using *{box-sizing: border-box;} in one of my projects (deployed in production, averaging over 1mln visits a month) at work for about a year now, and it seems to be holding up just fine. The project has been tested in IE8 & 9 and the latests Firefox and Chrome versions and we've had no problems. All jQuery (+UI) offset calculations and animations run fine, even in any element we've displayed as inline-block. As of late we've started testing the project on mobile devices (iPhone, iPad and Android) and we've had no issues regarding box-sizing with any of them yet, so it seems to work just fine.
One of my favorite use-cases that border-box solves well is columns. I might want to divide up my grid with 50% or 20% columns, but want to add padding via px or em. Without CSS's upcoming calc() this is impossible... unless you use border-box. So easy. :) Another good one is applying 100% width and then wanting to add a padding to that element.
Performance
Lastly on @miketaylr's inquiry, I also tested perf overhead. Anecdotal evidence suggests border-box isn't significant.
You might get up in arms about the universal * selector. Apparently you've heard its slow. Firstly, it's not. It is as fast as h1 as a selector. It can be slow when you specifically use it like .foo > *, so don't do that. Aside from that, you are not allowed to care about the performance of * unless you concatenate all your javascript, have it at the bottom, minify your css and js, gzip all your assets, and losslessly compress all your images. If you aren't getting 90+ Page Speed scores, it's way too early to be thinking about selector optimization. See also: CSS Selector Performance has changed! (For the better) by Nicole Sullivan.
So... enjoy and hope you'll find this a far more natural layout model.
02.01.2012: Added a section on performance
2012.02.03: Included webkit prefixed property and usecase of a 100% width box.
2012.02.22: Added link to Jeff Kaufman's history page.
This Wednesday, me and a ragtag team of like-minded developers launched Move the Web Forward, an initiative to direct people's passions into productive efforts that assist not only the web community but the entire web platform. People often feel the need to "give back", but when it comes to contributing it's a challenge to find the right place. This is something I've seen happen firsthand in the jQuery and HTML5 Boilerplate communities.
The MWF effort was inspired by a tweet by WebKit extraordinaire Dimitri Glazkov. Me and Divya started brainstorming on an etherpad. We rounded up some folks on Google+ and IRC and started collecting a lot of excellent resources. Soon after a design was in the making and we started working in an open repo on github…
At this point, I want to call out Mat Marquis aka @wilto, in particular, for really taking early ownership of this project and spearheading the design and frontend development. His efforts really made the site communicate its content effectively.
Naturally the site is on github if you'd like to contribute. We have a few issues open that we'll be improving the site with. (Also, let me just say for projects like this, a cron job to pull latest from Github makes for such a relaxing workflow.)
Thanks to Divya, Mat, Aaron Forsander, Connor Montgomery, Stephanie Rewis (great writeup!), Nicolas Gallagher, Addy, and all these awesome folk. Truly a socially developed site; everyone collaborating on IRC, etherpad and github (with as many having commit rights as possible). Fun project to work on and I hope to see everyone find the right place for them to get more involved in actively making the web as awesome as you want it to be.
2011.12.02: #movingwebforward in action!
Beyond all the people who signed up (with the avatars) on the site to commit to things.. We've seen some moves in the community already:
While a lot of conversation has moved to twitter and G+, hugely useful information is still published regularly to blogs. I've shared collections of frontend development feeds twicebefore. Now I'm back, but with two choices:
It's easy to click through and subscribe in Google Reader. There is also OPML files if you want to take 'em elsewhere.
Also, a short commentary on blogging vs tweeting.. while a lot of people have changed to twitter+jsfiddle only, tweets are not available via search after 30 days, so if you expect anything you share to last, blog it for real. :)
quick protip: In google reader it's best to set Reader to only Show updated (screenshot), so your left sidebar doesn't show feeds with nothing new in 'em. #shouldbedefault
2011.12.02: Adding newsletters!
Also please subscribe to these guys which do a great job of highlighting the top stories of the week: