惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Vercel News
Vercel News
O
OpenAI News
Engineering at Meta
Engineering at Meta
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
月光博客
月光博客
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
GbyAI
GbyAI
T
The Blog of Author Tim Ferriss
Google DeepMind News
Google DeepMind News
B
Blog RSS Feed
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
云风的 BLOG
云风的 BLOG
罗磊的独立博客
S
SegmentFault 最新的问题
The Register - Security
The Register - Security
Hugging Face - Blog
Hugging Face - Blog
D
DataBreaches.Net
U
Unit 42
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
B
Blog
阮一峰的网络日志
阮一峰的网络日志
P
Proofpoint News Feed
雷峰网
雷峰网
V
Visual Studio Blog
小众软件
小众软件
aimingoo的专栏
aimingoo的专栏
N
Netflix TechBlog - Medium
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Y
Y Combinator Blog
博客园 - 【当耐特】
G
Google Developers Blog
L
LangChain Blog
Stack Overflow Blog
Stack Overflow Blog
I
InfoQ
Martin Fowler
Martin Fowler
F
Fortinet All Blogs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The Cloudflare Blog
AI
AI
Google Online Security Blog
Google Online Security Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
博客园 - Franky
Blog — PlanetScale
Blog — PlanetScale
Webroot Blog
Webroot Blog
PCI Perspectives
PCI Perspectives
爱范儿
爱范儿
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org

CSS Wizardry

Front-End’s Missing Metric: The TBT Window Meet Your Users Where They Are with Obs.js Better Browser Caching with No-Vary-Search font-family Doesn’t Fall Back the Way You Think What Is CSS Containment and How Can I Use It? When All You Can Do Is All or Nothing, Do Nothing Obs.js: Context-Aware Web Performance for Everyone Low- and Mid-Tier Mobile for the Real World (2025) The Fastest Site in the Tour de France Making Sense of the Performance Extensibility API Why Do We Have a Cache-Control Request Header? HTML Is Not a Programming Language… Build for the Web, Build on the Web, Build with the Web Licensing Code on CSS Wizardry A Layered Approach to Speculation Rules Designing (and Evolving) a New Web Performance Score Core Web Vitals Colours The Ultimate Contract Templates for Tech Consultants: Protect Your Business and Get Paid Optimising for High Latency Environments Cache Grab: How Much Are You Leaving on the Table? blocking=render: Why would you do that?! Correctly Configure (Pre) Connections The Three Cs: 🤝 Concatenate, 🗜️ Compress, 🗳️ Cache What Is the Maximum max-age? How to Clear Cache and Cookies on a Customer’s Device The Ultimate Low-Quality Image Placeholder Technique Core Web Vitals for Search Engine Optimisation: What Do We Need to Know? The HTTP/1-liness of HTTP/2 In Defence of DOM­Content­Loaded Site-Speed Topography Remapped Why Not document.write()? Speeding Up Async Snippets Critical CSS? Not So Fast! Measure What You Impact, Not What You Influence Optimising Largest Contentful Paint Measuring Web Performance in Mobile Safari Site-Speed Topography Speed Up Google Fonts Real-World Effectiveness of Brotli Performance Budgets, Pragmatically Lazy Pre-Browsing with Prefetch Making Cloud.typography Fast(er) Time to First Byte: What It Is and How to Improve It Self-Host Your Static Assets Tips for Technical Interviews Cache-Control for Civilians Bandwidth or Latency: When to Optimise for Which ITCSS × Skillshare What If? CSS and Network Performance The Three Types of Performance Testing Getting to Know a Legacy Codebase Image Inconsistencies: How and When Browsers Download Images Identifying, Auditing, and Discussing Third Parties My Digital Music Setup Measuring the Hard-to-Measure Finding Dead CSS The Fallacies of Distributed Computing (Applied to Front-End Performance) Ten Years Old Relative Requirements Airplanes and Ashtrays Performance and Resilience: Stress-Testing Third Parties Refactoring Tunnels Little Things I Like to Do with Git Writing Tidy Code Configuring Git and Vim Base64 Encoding & Performance, Part 2: Gathering Data Base64 Encoding & Performance, Part 1: What’s Up with Base64? Code Smells in CSS Revisited Typography for Developers Moving CSS Wizardry onto HTTPS and HTTP/2 Ack for CSS Developers A New Year, a New Focus Preparing Vim for Apple’s Touch Bar Choosing the Correct Average CSS Shorthand Syntax Considered an Anti-Pattern CSS Wizardry Newsletter Nesting Your BEM? Improving Perceived Performance with Multiple Background Images Continue Normalising Your CSS Pure CSS Content Filter Pragmatic, Practical, and Progressive Theming with Custom Properties Refactoring CSS: The Three I’s Speaker’s Checklist: Before and After Your Talk Improving Your CSS with Parker The Importance of !important: Forcing Immutability in CSS Mixins Better for Performance Managing Typography on Large Apps White October Events Workshop Partnership BEMIT: Taking the BEM Naming Convention a Step Further Travelling Like You Want to, When You Have To Contextual Styling: UI Components, Nesting, and Implementation Detail Subtleties with Self-Chained Classes Cyclomatic Complexity: Logic in CSS Immutable CSS Can CSS Be Too Modular? More Transparent UI Code with Namespaces When to use @extend; when to use a mixin The Specificity Graph CSS Wizardry Ltd.: Year 1 in review
Hacker News rebuttal
Harry Roberts · 2012-03-13 · via CSS Wizardry

Written by on CSS Wizardry.

Table of Contents

Independent writing is brought to you via my wonderful Supporters.

Yesterday I decided to post on Hacker News something I’ve recently been working on for both myself and Sky. That something was a list of guidelines as to how best write CSS for manageable and maintainable projects.

Unfortunately, a number of the HN community didn’t take so well to my points so I’ve decided to publish a full response, as opposed to the disjointed and frankly unprofessional comment discussion that was emerging.

One user in particular took exception to a lot of my advice and it is his issues I shall address most directly. This isn’t a vendetta at all, more my trying to answer his and others’ concerns at large. He offered a pretty 1:1 comeback to a lot of my points so I shall try to maintain a similar format here.

I may paraphrase a lot here so I urge you, please, read the original thread. I apologise and regret and instances in which I come across as rude and/or unprofessional; I acted on impulse rather than rationally, as I should have done.


I said:

For each level of markup nesting, try and indent your CSS to match.

He said:

Nope.

Indenting CSS to mirror your markup structure can be very useful for a number of reasons, chief among which is the ability to see at a glance how the listed CSS selectors should be used in HTML. For example, when building a carousel, I often find myself with CSS selectors like:

.carousel{}
.panes{}
.pane{}
.slide-image{}
.slide-title{}

As these selectors are only one class deep it is difficult to see at a glance how they might map to my HTML. One solution might be to write my CSS like so:

.carousel{}
.carousel .panes{}
.carousel .panes .pane{}
.carousel .panes .pane .slide-image{}
.carousel .panes .pane .slide-title{}

But of course you don’t need me to tell you how nasty that is…

Instead, I prefer a structure more like:

.carousel{}
    .panes{}
        .pane{}
            .slide-image{}
            .slide-title{}

Here my selectors are still nice and short but I can still see how they map to my HTML structure. I find this really useful to see at a glance how these rules relate to one another.

If you don’t like this, or won’t find it useful, that’s cool! Just don’t use it.


I said:

Also write vendor prefixed CSS so that colons all line up

He said:

Nope

I really have no idea why you wouldn’t do this one. It’s often been proposed that we should write vendor prefixed CSS thus:

-webkit-border-radius:4px;
   -moz-border-radius:4px;
        border-radius:4px;

This means all our values—the bits that matter the most—are lined up to a) scan quickly and b) edit at once with columnal typing (in text editors which support it). This, to me, is a no-brainer and a very quick-win.


I said:

Instead of building dozens of unique components, try and spot repeated design patterns abstract them; build these skeletons as base ‘objects’ and then peg classes onto these to extend their styling for more unique circumstances.

He said:

[Not unless you are a big website like Facebook]

It doesn’t matter if you are working on the next Facebook or for some guy from the pub, if you can build a website from several repeated components you should. From a performance, consistency, maintainability and sheer sensibility point of view, don’t solve the same problem a dozen times when you can solve it once with an abstraction.

Best practices are best practices, the size of a project is irrelevant.


I said:

All components should be left totally free of widths; your components should always remain fluid and their widths should be governed by a grid system.

He said:

Nope. Again, grid systems are something that should be used on a case-by-case basis, according to the nature of the site you’re building.

Here I made something of a mistake; when I say grid system what I actually mean is any means of abstracting your layout into its own layer.

If this is a grid system then this is simple; a grid system handles your layout and your components fill it.

If you are not using a grid system then wrapper and parent elements should handle layout and the components should still say fluid. As I said on Twitter just three days prior to this:

Box-model properties are the most fragile and unpredictable and thus should be avoided wherever you can. Leave layout to wrappers/parents… (#)

And:

When sites break it‘s usually because of layout—the less layout stuff we declare the less chance it has to break. Abstract layout to grids! (#)

Whether using a grid system or not, your components should not carry dimensions. Think of a page like a set of shelves; you set up your shelving units (grid system (or similar)) and then populate them with things (components). If you didn’t have the shelves erected then the components would be supporting themselves, holding themselves up; this makes moving or changing them very volatile.

Abstract your layout to wrappers, parents or grid systems, always.


I said:

Heavily location-based selectors are bad for a number of reasons.

He said:

Nope. What you’re arguing against is a rule that has a high degree of specificity…

I’m not; I’m talking about location based styling. As soon as an elements begins to rely on its parent, and their parent, and their parent’s parent then you are doing it wrong. Your styles should never rely too heavily on where they live as this makes them incredibly unportable.

Putting classes on the elements you wish to affect rather than drilling down to them via the DOM tree is a lot better in terms of portability in that you don’t have to rely on a location in order to set styles. This one really is a no-brainer for me…


I said:

An over-qualified selector is one like div.promo.

He said:

[This is actually a good idea unless you want a class to be applicable to any element]

Erm, yes please! Ideally classes are applicable to any element; classes should be element-agnostic. The ability to apply them to any element we wish is exactly what we want.

Why would you ever, ever write div.promo{} in your stylesheet if that could be left at .promo{}?! Why would you ever limit yourself to only being able to use a class on one type of element when you could leave the leading type selector off and have an element-agnostic rule?

This is another no-brainer to me. Don’t tie yourself to things when you really just don’t need to. I think we can all agree that .promo{} is a lot more (re)usable than div.promo{}. By tying an element to any class you are the only thing that will hinder you going forward; you are preemptively closing a lot of doors on yourself…


I said:

Do not use IDs in CSS at all.

He said:

“NOPE NOPE NOPE NOPE NOPE. Understand specificity rules. Write good selectors. Don’t outright ban IDs just because you’re not careful enough to write clean CSS.”

I’m pretty sure no CSS developer has ever said ‘I wish I’d used an ID here instead of a class.’

IDs work, sure, but they are way too specific. It doesn’t matter how good a developer you are, you cannot change the fact that an ID is massively more specific than a class.

I would genuinely love to see an elegant solution to this that doesn’t use a class over an ID. (There isn’t one.)

There is literally no reason why, from a purely CSS point of view, that an ID is better than a class. An ID is impossible to reuse (whether you want to or not) and they have a way-over-the-top specificity.

Anything you can do with an ID can be done with a class, but with none of the drawbacks. IDs will only ever trip you up because you can never reuse them and they will trump your class-based-selectors by quite an order of magnitude.

Classes; all the bits you love about IDs with none of the bits that are like IDs.

To me, another no-brainer.


I said:

As a general rule, all layout and box-model rules can and will work without an IE stylesheet if you refactor and rework your CSS.

He said:

Hahahahahahahahahhaa

I was the sole CSS developer on Sky Bet. This project (as a whole) has taken over a year for the whole team involved (and almost a year of my dev time).

To support IE7+ I used all of zero IE stylesheets. Not one. A project which took me almost a year did not require one single IE stylesheet. It is doable, it should be done.

I haven’t written an IE stylesheet in all of my professional career. I started working when I was 18 so that makes three years; I haven’t written an IE stylesheet in over three years. It’s not that hard, seriously.

To just laugh off such a statement seemed a little odd, but seriously, if you invest enough time and take enough care, you will not need an IE stylesheet.


Like I said in the documents’s README, you can disregard the advice if you wish, but make sure you fully understand it before shunning it completely.