Skip to Content

Is Progressive Enhancement Dead Yet?

Progressively enhancing web applications is not only an essential practice for accessibility, but it provides a framework to respect separation of concerns in technology _and_ reduce boilerplate, polyfills, and otherwise kludgy code.

Pickering wants to talk about Progressive Enhancement, but ap­par­ently a lot of peo­ple are over it and want to be done with it. Pickering thinks that putting pro­gres­sive en­hance­ment to bed — and wor­ry­ing about it no more would be a grave” mis­take.

Pickering ad­dresses some com­mon mis­con­cep­tions.

Progressive Enhancement is Not:

Pickering uses an metaphor of the skate­board to ex­plain what pro­gres­sive en­hance­ment is.

Imagine two skate­boards. One is the old fash­ioned kind, it’s just a board with wheels. The other has a screw hole near the front, al­low­ing you to at­tach some han­dle­bars and make the skate­board a scooter. Just be­cause the han­dle­bars don’t at­tach to the older skate­board does­n’t mean it’s bro­ken. It still works as a skate­board.

In Pickerings ex­am­ple, the han­dle­bars are a fea­ture that the browser may or may not sup­port. Importantly, if there is no sup­port for the fea­ture, things still work fine. Great em­pha­sis is placed on this point.

The ba­sic lay­out is not a bro­ken lay­out.

Here’s a pro­vide ex­am­ple of a pro­gres­sively en­hanced ma­sonry lay­out:

.grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);

@supports (grid-template-rows: masonry) {
	.grid {
		.grid-template-rows: masonry;

If a browser sup­ports @supports and grid-template-rows:masonry, the lay­out en­gine ap­plied the lay­out. The key here is that out lay­out tools are han­dling out lay­out, and Javascript is not re­lied on at all for func­tions that Javascript is not in­tended for.

Another ex­am­ple, us­ing is pro­vided:

// use web component
	widthBreaks="320px, 60ch"
	heightBreaks="100vh, 2014px" 
	<!-- children -->

// progressive enhancement logic 
if ('ResizeObserver' in window && 'customElements' in window) {
	customElemeents.define('watched-box', WatchedBox);

// load custom element as module
<script type="module" src="watched-box.js"></script

The mod­ule im­port self-se­lects for mod­ern browsers, the cus­tom el­e­ment code it­self checks for browser fea­ture sup­port, and if none of these things ex­ist the chil­dren of the <watched-box> tag ren­der nor­mally.

Another ex­am­ple of con­di­tion­ally im­port­ing Javascript:

// ignored by old browsers, used by modern browsers
<script type="module" serc="new.js"></script>

// ignored by modern browsers, used by old browsers
<script nomodule src="old.js"></script>

This is all pred­i­cated on re­spect­ing the sep­a­ra­tion of con­cerns for HTML, CSS, and JS, and it’s im­por­tant that we don’t do thing in JS that could and should be done with CSS.

Pickering closes with a counter-ex­am­ple of re­gres­sive en­hance­ment with a tab pat­tern. This pat­tern is bet­ter han­dled in a tra­di­tional HTML struc­ture, as adding large amount of Javascript to col­lapse the pat­tern into tabs cre­ate both an ac­ces­si­bil­ity and user ex­pe­ri­ence night­mare that can be hugely dif­fi­cult to un­tan­gle. Pickering iden­ti­fied the im­por­tant of let­ting the browser tech­nolo­gies do their thing.

The fi­nal note is as fol­lows:

Use Javascript to do Javascript things. And not Javascript to do like … not Javascript things.