For years, using a new CSS feature meant writing it three or four times. Vendor prefixes were the mechanism behind that: special identifiers added to a property to mark it as experimental or browser-specific while a feature was still being standardised. They let developers use cutting-edge properties early, before the specification settled, with each browser engine opting in through its own prefixed version. Understanding them still matters, both for reading older codebases and for knowing the handful of cases where they linger, but the most important modern lesson is that you almost never need to write them by hand anymore. This article explains what they are, how they work, and how to handle them today.
What a vendor prefix is
A vendor prefix is a short tag in front of a property name that ties it to a particular browser engine, signalling that the feature was experimental or non-standard in that engine at the time. There are four you will encounter. The -webkit- prefix belongs to Chrome, Safari, newer Opera, and other WebKit and Blink based browsers. The -moz- prefix belongs to Firefox. The -ms- prefix belongs to Internet Explorer and legacy Edge. And the -o- prefix belongs to older versions of Opera. So a single feature might appear four times, once per engine, before the unprefixed standard version existed in any of them.
Why they existed
Prefixes solved a real problem during a long period when browsers implemented new CSS faster than the standards process could finalise it. They gave three things. They provided browser compatibility, letting a new feature work across engines that had each implemented it slightly differently. They supported progressive enhancement, so you could use an advanced effect while older browsers safely ignored what they did not understand. And they enabled testing and development, letting both browser makers and developers experiment with a feature before it was locked down, with the prefix acting as a clear “this is not final” marker.
How they are written
The rule that governs prefixes is order. You list the prefixed versions first and the standard, unprefixed version last, so that any browser supporting the final standard uses it and overrides the experimental ones above. A transition written the old way shows the pattern.
.button { -webkit-transition: background-color 0.3s ease; -moz-transition: background-color 0.3s ease; -o-transition: background-color 0.3s ease; transition: background-color 0.3s ease;}
Each engine reads the line it recognises and ignores the rest, and the standard line at the bottom wins wherever it is supported. Transforms followed the same shape, including the Internet Explorer prefix.
.box { -webkit-transform: rotate(45deg); -moz-transform: rotate(45deg); -ms-transform: rotate(45deg); -o-transform: rotate(45deg); transform: rotate(45deg);}
The standard property always comes last so that a modern browser, which understands the unprefixed form, applies it rather than the experimental version above.
Where they used to be needed
A predictable set of features went through a prefixed phase, and recognising them helps when you read older stylesheets. Transitions used -webkit-, -moz-, and -o- for smooth state changes. Transforms added -ms- on top of those for rotating and scaling. Animations needed the same engine prefixes for keyframe work. Flexbox was a particularly messy case, with -webkit- and -ms- versions and even older alternative syntaxes during its evolution. Gradients had divergent early syntaxes, including an old -webkit-gradient form. And box shadow carried -webkit- and -moz- versions before it settled. Almost every visually interesting property of that era passed through this stage.
How to handle prefixes today
Here is the part that matters most now. The great majority of these properties are fully standardised, and current browsers support the plain, unprefixed versions, so hand-writing four copies of a transition is wasted effort and clutter. The modern approach is to write the standard property once and let tooling add any prefixes that are genuinely still required.
A few principles keep this clean. Respect the ordering rule whenever you do write prefixes manually, standard property last, so support is layered correctly. Keep it minimal, and check current browser support data rather than copying prefix lists out of habit, because most are now obsolete. Above all, use Autoprefixer, a build tool that reads your plain CSS and adds exactly the prefixes your target browsers need, based on real support data, then removes them as they become unnecessary. This keeps your source clean and always up to date without you tracking the state of every feature yourself. And as ever, provide a sensible fallback for anything an old browser might not support even with a prefix, so the layout degrades gracefully rather than breaking.
Flexbox is the classic example of where a tool earns its keep, because its history left several syntaxes behind.
.container { display: -webkit-box; display: -ms-flexbox; display: -webkit-flex; display: flex; -webkit-align-items: center; -ms-flex-align: center; align-items: center; -webkit-justify-content: space-between; -ms-flex-pack: justify; justify-content: space-between;}
That verbosity is exactly the kind of thing you should never type by hand. You write the three clean standard lines, display: flex, align-items: center, and justify-content: space-between, and let Autoprefixer expand them only if your browser support targets actually call for it.
Conclusion
Vendor prefixes were how the web shipped new CSS during a decade when implementation outran standardisation, with -webkit-, -moz-, -ms-, and -o- each marking a browser’s experimental take on a feature. The mechanics still matter for reading legacy code: list prefixed versions first and the standard last so modern browsers win. But the practical takeaway for new work is the opposite of the old habit. Write the standard property once, keep your source clean, and let Autoprefixer add the rare prefix that is still needed, rather than maintaining stacks of them by hand. The era of writing every property four times is over, and that is a good thing.
See you soon.
[…] wins available, because it shrinks your stylesheets on the network without touching a line of your CSS. Minify first to clean the file, then let the server or CDN encode it with Gzip or Brotli, […]
[…] Vendor Prefixes: https://datalad.co.uk/css-vendor-prefixes/ […]
[…] CSS gradients give you smooth, scalable colour transitions with no image files and no extra requests. Use a linear gradient to blend along a line with a direction or angle, a radial gradient to radiate from a point with a shape and size, and a conic gradient to sweep colours around a centre for wheels and pie charts, with repeating variants of each for stripes and patterns. Control the blend precisely with positioned colour stops and their percentages, provide a solid fallback colour for safety, go easy on the most complex gradients for performance, and keep your colours in custom properties so the whole scheme stays consistent. With these, you can add depth and polish to a design using nothing but CSS. […]