The Problem with Web Development Checklists, or: The Frontend Checklist, Revised
Post from June 19, 2019 (↻ March 31, 2020), filed under Web Development.
Checklists sound like a great way to make sure nothing gets forgotten for a mission or a project. That’s especially true when something valuable is at stake, as I personally learned when starting to make my helicopter pilot license and running around helicopters marking off, checklists. Yet checklists are problematic when they contain items that aren’t important—the unnecessary fluff causes unnecessary work and, in web development, unnecessary code.
In web development, checklists are also problematic because there are many different types of projects—which means that there’s only a small intersection of things that all projects have in common. Yet, just as with frameworks and libraries, where likewise more needs are assumed than our projects actually have—the main problem with public frameworks, as I noted in my frameworks book—, most checklists, and all I’ve seen so far, ignore this issue, asking to check for matters that are not relevant.
This may happen then for a particular reason: The beauty of the true and tiny number of commonalities between all projects and their needs is not perceived. Or discarded, as too simple, too unclever, too uninteresting. A taste? The “World’s Best HTML Template,” which provocatively but truthfully contains all code that any website needs and that easily gets dismissed out of hand. Very well: How is this helpful? But the dismissal also represents some intellectual laziness, not acknowledging how little, strictly speaking, any two websites really have in common.
Even when this accusation of laziness is harsh, then, and even when there can be some value in checklists (and frameworks), and even when some have managed to develop or use checklists (as well as frameworks) so that their application was nothing but advantageous, I’ll conclude this part with a recommendation:
For maximum quality, write your own checklists.
Figure: It appears useful to learn curious things. (Copyright King Features Syndicate, Inc., distr. Bulls.)
This DYI is work, and yet I’ll now demonstrate why that work is rather needed. Here’s a quick and of course opinionated review of The Frontend Checklist, as of its May 23, 2019, checks, with brief commentary on what’s useful, questionable, and, at the moment, useless, without regard for the priority The Frontend Checklist assigns each item. (I share this with a lot of respect, then, as the following is not meant to downplay or dismiss the work that was done.)
The Frontend Checklist: Use 33, Question 13, Ignore 41 Items
Doctype: The doctype is HTML5 and is at the top of your HTML pages
👎: Meant is the doctype for living HTML (where the spelling “HTML5” has always been a bit silly) and yet this check is somewhat useless—there should be a doctype declaration, one that’s validated against, but there’s nothing inherently wrong with other doctypes.
Charset: The charset declared (UTF-8) is declared correctly
👎: Too vague, overly specific. There are many ways to declare an encoding (which is meant) and the encoding can well be recommended to be UTF-8 but may by all means also be something else—as long as the document actually uses and indicates that encoding.
Viewport: The viewport is declared correctly
✋: This is also rather vague, it’s also likely difficult to defend in all scenarios, but may be acceptable as a requirement.
Title: A title is used on all pages
👍: This is important; absence of a
title is easily caught, especially when validating, but the rule is, per se, okay.
Description: A meta description is provided, it is unique and doesn’t possess more than 150 characters
👎: I know it’s not a popular stance but from my view, meta descriptions are a software problem; and even if one maintains that they must be pushed on humans, it doesn’t follow that this was mandatory, that a website could not live without meta descriptions. It can (qed, per this very site).
Favicons: Each favicon has been created and displays correctly
✋: This is an odd rule, and the oddness begins with “each.” One can argue that having a favicon is good practice, but somewhat suggesting each of more than 45 (!) known icons needs to be supported to pass some random test looks crazy. As does the general situation around favicons.
Apple web app meta: Apple meta tags are present
👎: Too broad and unspecific. Apple has invented so much meta information over the years that following this guideline is akin to making every HTML page the size of the Encyclopædia Britannica. (There are useful Apple meta elements. Which ones these are exactly, beats me.)
Windows tiles: Windows tiles are present and linked
👎: Likewise too broad and unspecific—don’t take action. If it’s not clear how that’s too broad, imagine an HTML checklist item “HTML elements are present.” Or perhaps a shopping list, “groceries are present.” Guidelines like that have no value.
rel="canonical" to avoid duplicate content
👎: This is a poorly worded guideline because it simply, overly broadly assumes that there is, in fact, duplicate content (most sites probably don’t suffer from that). It would be a lot better if this said “if major parts of the content are also used on other pages, use
rel="canonical" to reference the page that’s the source of truth,” or something like that.
Language attribute: The
lang attribute of your website is specified and related to the language of the current page
👎: No. But even if one insists on providing language information for a page, that can be done easier on the server-side.
Direction attribute: The direction of is specified on the
html tag (it can be used on another HTML tag)
👎: Meant is the
html start tag (or
html element), of course, but since absence of
@dir defaults to
ltr, the attribute does not need to be specified on LTR pages.
Alternate language: The language tag of your website is specified and related to the language of the current page
👎: It’s unclear what this rule is about. Document language has already been covered, site language is handled the same way, and language changes within a document do not work through “the language tag of the website.”
Conditional Comments: Conditional Comments are present for if needed
👎: No. (I thought Conditional Comments were dead.)
RSS feed: If your project is a blog or has articles, an RSS link was provided
👎: A wholehearted “yes” in spirit, but after Google’s war on feeds it’s become really hard to argue that feeds were a hard requirement, even for content sites. I personally really wish they were, I’m with this, but such a rule is not defensible unless feeds were as popular as they were, say, 2006–2013.
Inline critical CSS: The inline critical CSS is correctly injected in the head
👎: This rule depends on so many conditions (per the first paradigm it would only be justifiable on one-pagers) that it has no place (yet) in an all-purpose dev checklist.
👍: Not an iron rule but sound.
Facebook Open Graph
👎: No. This rule suggests every site must be catering for Facebook and that position cannot be held—for one it’s not hard to imagine that some sites don’t choose to do anything with Facebook, for another, and perhaps more importantly, even without special Facebook meta information sites can be shared on Facebook, even in an okay-looking way.
👎: No. The same as with Facebook. Nice to have, yes. Compulsory for every website out there, no.
HTML5 Semantic Elements: HTML5 Semantic Elements are used appropriately (
👍: Yes: All HTML elements want to be used according to their purpose.
Error pages: Error 404 page and 5xx exist
✋: Tricky rule: In practice there’s already always some message, though it may not be very useful for the user. Yet a general demand for a 404 page may not provide anything more useful, and a demand to cover one, some, or all errors in the 500s range is too imprecise to form a good rule. Perhaps this could be saved by requiring a “useful page for 404 errors and other anticipated HTTP errors (like 401 in case of page authorization),” though that’s a bit vague, too.
noopener: In case you are using external links with
target="_blank", your link should have a
👍: One of several user agent problems forced on web developers, but yes.
Clean up comments: Unnecessary code needs to be removed before sending the page to production
✋: Yes and not yes. Yes because it’s surely an optimization step reducing payload (and eliminating a risk of conveying internal information—we used to think of this at Google), not yes because it may still depend, like when comments are few or desired (personally I like to point to meta information through comments).
W3C compliant: All pages need to be tested with the W3C validator to identify possible issues in the HTML code
HTML lint: I use tools to help me analyze any issues I could have on my HTML code
👍: This seems somewhat complementary and secondary but, yes. (Then, “I use”? Some guidelines use first person, others second, and then they switch between active and passive voice; this may be something to revisit.)
Link checker: There are no broken links in my page, verify that you don’t have any 404 error
Adblockers test: Your website shows your content correctly with adblockers enabled
✋: If a website contains ads, probably. But it may just be me here who not only believes it would be horrible to run after ad blockers—but that those ad blockers shouldn’t exist. (Indeed, I believe there are many strong reasons against ad blockers.)
Webfont format: WOFF, WOFF2 and TTF are supported by all modern browsers
👎: Phrased as it is here, this rule makes no sense: Why and how would an author be required to check that all modern browsers support these three or any three font formats? But with this rule likely suggesting that one could safely use either format, the 2019 recommendation seems to be to use WOFF2 and WOFF.
Webfont size: Webfont sizes don’t exceed 2 MB (all variants included)
👍: Arbitrary (perhaps still rather high) but, well.
Webfont loader: Control loading behavior with a webfont loader
👎: No. Keep it simple. Don’t fall for something that promises to reduce a complexity it itself compounds.
Responsive Web Design: The website is using responsive web design
👍: Yes. Make the site or app be responsive.
: A print stylesheet is provided and is correct on each page
Unique ID: If IDs are used, they are unique to a page
👍: A duplicate (this is taken care of with validation) but, yes.
Reset CSS: A CSS reset (reset, normalize or reboot) is used and up to date
👎: Absolutely not. Assume that anyone requiring you to use a reset doesn’t have a full grasp of web development. Seriously—it’s 2019, year of ever more equal default styling, and this rule would be much more useful if it instead suggested to remove any resets—and to watch the code base shrink while nothing even happens.
js- and are not styled into the CSS files
👎: Such a prefix is optional, could be anything, and could really also be tied to hooks used for styling if it forms a functional unit with respective component.
Embedded or inline CSS: Avoid at all cost CSS in
<style> tags or using inline CSS
👎: Most of the time, yes, all of the time, no. Prominent edge cases: One-pagers benefit from inline CSS code, and guaranteed unique styling could warrant that, too (for example, dimensions that may pertain to unique elements and that are unlikely to be repeated anywhere else).
Vendor prefixes: CSS vendor prefixes are used and are generated accordingly with your browser support compatibility
👎: Probably just poorly phrased as the rule appears appropriate once one adds “when needed.” Blindly requiring prefixes is poor advice.
Concatenation: CSS files are concatenated in a single file (not for HTTP/2)
✋: Perhaps not only not for HTTP/2, but also not in every single other case, and yet this is not a clear “no.”
Minification: All CSS files are minified
👍: I could see exceptions but, yes.
Non-blocking: CSS files need to be non-blocking to prevent the DOM from taking time to load
Stylelint: All CSS or SCSS files are without any errors
Responsive web design: All pages were tested with the correct breakpoints
CSS validator: The CSS was tested and pertinent errors were corrected
Desktop browsers: All pages were tested on all current desktop browsers (Safari, Firefox, Chrome, Internet Explorer, Edge…)
👎: Yes, but no. Yes of course, in a sense of absolutely testing that a site or app works. But no for two reasons: 1) the actual browsers to test for depend on audience and priorities, 2) this rule could better be rephrased and combined with the following two checks:
Mobile browsers: All pages were tested on all current mobile browsers (Native browser, Chrome, Safari…)
👎: No, make this one testing guideline that is dependent on audience and priorities.
OS: All pages were tested on all current OS (Windows, Android, iOS, Mac…)
👎: No, make this one testing guideline that is dependent on audience and priorities.
Reading direction: All pages need to be tested for LTR and RTL languages if they need to be supported
👎: This is already implicitly handled with the other testing requirements.
👍: Yes. Perhaps one of the few remaining places where Separation of Concerns is not under (questionable) siege.
✋: Perhaps, as with CSS, not only not for HTTP/2, but also not in every single other case, but again not a clear “no.” Probably do this regardless.
👍: Rather yes.
noscript tag: Use
<noscript> tag in the HTML body if a script type on the page is unsupported or if scripting is currently turned off
✋: Probably good advice, but probably not mandatory.
Modernizr: If you need to target some specific features you can use a custom Modernizr to add classes in your
👎: “If … you can” makes no good guideline.
ESLint: No errors are flagged by ESLint (based on your configuration or standards rules)
✋: Probably good, but both the push to use ESLint as well as vagueness with respect to the ruleset make this a questionable requirement.
Optimization: All images are optimized to be rendered in the browser; WebP format could be used for critical pages (like Homepage)
👍: I find “optimized to be rendered in the browser” a bit odd (“compressed for suitable quality”?) but, yes. WebP doesn’t seem ready to me yet but does of course work with fallbacks.
srcset: You use
srcset to provide the most appropriate image for the current viewport of the user
👎: No, please. For one,
img may be a more compact alternative. For another, just
img may do as well.
Retina: You provide layout images 2× or 3×, support retina display
👎: No, not as a rule of thumb (at least not for me). There are enough cases when higher quality images don’t warrant the extra effort and code.
Sprite: Small images are in a sprite file (in the case of icons, they can be in an SVG sprite image)
✋: It probably depends but with the growing reach of both HTTP/2 and inlining SVGs I’d deem sprites to diminish in importance.
Width and height: Set
height attributes on
<img> if the final rendered image size is known (can be omitted for CSS sizing)
👎: Apart from when intrinsic sizing works, don’t we all work with CSS sizing?
Alternative text: All
<img> have an alternative text which describe the image visually
Lazy loading: Images are lazy-loaded (a
noscript fallback is always provided)
👎: As you can tell, the beef I’m having with many checklist points is not necessarily the practice itself but rather the lack of conditions and qualifiers. Why always load lazily—what if there are just a handful of icons of negligible file size? Don’t throw tooling at all the things. (As for lazy-loading, using
loading=lazy makes everything easier.)
Color contrast: Color contrast should at least pass WCAG AA (AAA for mobile)
👍: Yes, though I’m not sure about the stricter rule for mobile—my hunch, and yet just a hunch, is that that may be too strict.
h1: All pages have an
h1 which is not the title of the website
👎: Also a little hunch-y for in need of more research and elaboration, this may be an antiquated guideline if one assumes that user agents could just put headings in relation. For example, on a page where the highest heading level is an
<h3>, pronounce this the highest, and set other headings in relation. If there’s an
<h1> and then a
<h3>, don’t throw a “skipped heading” tantrum but relay
<h1> as most important,
<h3> as next important. If heading order was relative instead of absolute, authoring and accessing could both become easier. (Given CSS implications, maybe this is something for a different forum.)
Headings: Headings should be used properly and in the right order (
👍: No to absolute order, but yes to relative order (see above).
Specific HTML5 input types are used: This is especially important for mobile devices that show customized keypads and widgets for different types
👍: Yes, except for
Label: A label is associated with each input form element; in case a label can’t be displayed, use
Accessibility standards testing: Use the WAVE tool to test if your page respects the accessibility standards
✋: Yes on testing, no to limiting this to WAVE: There are quite a few accessibility testing tools out there.
Keyboard navigation: Test your website using only your keyboard in a previsible order; all interactive elements are reachable and usable
Screen reader: All pages were tested in two or more screen readers (such as JAWS, VoiceOver, and NVDA)
✋: “Two” needs elaboration when apparently three or more comparable options are given (otherwise, why give the choice of JAWS, VoiceOver, and NVDA?). When these and other options are all equal, testing in one screenreader would do. (I cannot credibly answer this, I’m not an expert when it comes to current web standard support in screenreaders.)
Focus style: If the focus is disabled, it is replaced by visible state in CSS
Page weight: The weight of each page is between 0 and 500 KB
👎: What is “page weight” here (just the HTML?), and what justifies the 500 KB that look quite random?
Minified HTML: Your HTML is minified
👍: I could see exceptions but, yes.
Lazy loading: Images, scripts and CSS need to be lazy loaded to improve the response time of the current page
👎: No, they don’t “need to.” Performance can be stellar without lazy loading; lazy loading is context-dependent.
Cookie size: If you are using cookies be sure each cookie doesn’t exceed 4,096 bytes and your domain name doesn’t have more than 20 cookies
DNS resolution: DNS of third-party services that may be needed are resolved in advance during idle time using
👍: I’m not sure about making this an iron rule but on the other hand it’s something that does speed things up.
Preconnection: DNS lookup, TCP handshake and TLS negotiation with services that will be needed soon is done in advance during idle time using
Prefetching: Resources that will be needed soon (e.g. lazy loaded images) are requested in advance during idle time using
👎: Probably not. In this case I’m switching course because when the guidelines end up requiring everything to be preconnected and prefetched, the rules become meaningless and should rather be filed as requests with vendors (prefetch everything). Requiring all resources to be loaded in advance looks exaggerated to me.
Preloading: Resources needed in the current page (e.g. scripts placed at the end of
<body>) in advance using
Google PageSpeed: All your pages were tested (not only the homepage) and have a score of at least 90/100
Google Analytics: Google Analytics is installed and correctly configured
👎: No. First, only when you actually need it, second, there are other analytics tools.
Headings logic: Heading text helps to understand the content in the current page
👎: What is this rule about—heading levels or copy?
sitemap.xml: A sitemap.xml exists and was submitted to Google Search Console
✋: Originally a clear “no” because Google seems pretty good in catching pages on websites (unless not linked or excluded in robots.txt), but perhaps there’s something I miss and need for certainty outweighs such practical concerns.
robots.txt: The robots.txt is not blocking webpages
👎: Very likely just poorly phrased as of course, there could be very good reasons to block pages. Therefore, a general ban on exclusions appears overdone.
Structured Data: Pages using structured data are tested and are without errors
👍: If they do, yes.
Structured data helps crawlers understand the content in the current page
👎: What does that mean or, for understanding, what’s a good counter-example for this—are there structured data that would confuse crawlers in a way that’s unrelated to content and not affected by the previous guideline?
Sitemap HTML: An HTML sitemap is provided and is accessible via a link in the footer of your website
👎: No, because not every website needs a sitemap and even if it would, there could be more suitable locations for their link than in the footer.
Pagination link tags: Provide
rel="next" to indicate paginated content
❧ I believe this makes for a particular review of contemporary web development priorities, and certainly for substantial feedback for The Frontend Checklist. They, then, should not feel deterred: Their own great potential may not necessarily lie in an always applicable checklist for web developers (then, as we see, the list gets a lot shorter), but to make it a skeleton, a foundation for less experienced developers to learn about details and qualifiers of the craft.
There are problems with checklists, but they’re certainly not without use.
I’m Jens Oliver Meiert, and I’m a web developer and author. I love trying things, including in the fields of philosophy, art, and adventure. Here on meiert.com I share some of my views and experiences.
If you have any suggestions or questions about what I write, leave a comment or a message.
Have a look at the most popular posts, possibly including:
- 3 Reasons Against Ad Blockers
- Image Compression: How to Super-Easily Set Up Automated Base Optimization
Perhaps my most relevant book: CSS Optimization Basics (2018). Writing CSS is a craft. As craftspeople we strive to write high quality CSS. In CSS Optimization Basics I lay out some of the most important aspects of such CSS. (Also available in a bundle with Upgrade Your HTML.)
Looking for a way to comment? Comments have been disabled, unfortunately.