Browser loads styles in several stages:
/* Critical styles load first */
<link rel="stylesheet" href="critical.css">
/* Non-critical can be deferred */
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">Style loading is a complex process that affects page display speed! Browser must not only download CSS but also process it correctly. 🚀
Browser finds style links and starts loading them:
<!-- Blocking load -->
<link rel="stylesheet" href="styles.css">
<!-- Preload -->
<link rel="preload" href="fonts.css" as="style">
<!-- Conditional load -->
<link rel="stylesheet" href="print.css" media="print">Browser breaks CSS into tokens and rules:
/* Parser processes selectors */
.header { color: blue; }
#main { font-size: 16px; }
div > p { margin: 10px; }
/* And media queries */
@media (max-width: 768px) {
.mobile { display: block; }
}CSS Object Model is created:
/* Style hierarchy */
body {
font-family: Arial;
color: black;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.header {
background: #f0f0f0;
padding: 20px;
}CSS blocks rendering until fully loaded:
<!-- Blocks rendering -->
<link rel="stylesheet" href="main.css">
<!-- Doesn't block for print -->
<link rel="stylesheet" href="print.css" media="print">
<!-- Async loading -->
<link rel="preload" href="async.css" as="style" onload="this.rel='stylesheet'">Browser applies rules by priority:
/* Specificity: 1 */
p { color: black; }
/* Specificity: 10 */
.text { color: blue; }
/* Specificity: 100 */
#content { color: red; }
/* Specificity: 1000 */
p { color: green !important; }Browser calculates final styles:
/* Relative units */
.container {
width: 80%; /* Computed from parent */
font-size: 1.2em; /* Relative to parent font */
margin: 2rem; /* Relative to root font */
}
/* Inheritance */
body { font-family: Arial; }
p { /* Inherits font-family */ }Inline important styles in HTML:
<style>
/* Critical styles for above-the-fold */
.header { background: #fff; height: 60px; }
.hero { min-height: 400px; }
</style>
<!-- Load other styles async -->
<link rel="preload" href="main.css" as="style" onload="this.rel='stylesheet'">/* Before minification */
.button {
background-color: #007bff;
border-radius: 4px;
padding: 8px 16px;
}
/* After minification */
.button{background-color:#007bff;border-radius:4px;padding:8px 16px}/* Used */
.header { display: flex; }
.button { padding: 10px; }
/* Unused - can be removed */
.unused-class { color: red; }
.old-component { margin: 20px; }Analyzing loading in DevTools:
// Measuring CSS loading time
performance.getEntriesByType('resource')
.filter(entry => entry.name.includes('.css'))
.forEach(entry => {
console.log(`${entry.name}: ${entry.duration}ms`);
});<!-- Inlined critical styles -->
<style>
.above-fold { /* styles for first screen */ }
</style>
<!-- Deferred loading of the rest -->
<noscript><link rel="stylesheet" href="main.css"></noscript><!-- Font preloading -->
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>
<!-- CSS preloading -->
<link rel="preload" href="styles.css" as="style"><!-- Only for large screens -->
<link rel="stylesheet" href="desktop.css" media="(min-width: 1024px)">
<!-- Only for print -->
<link rel="stylesheet" href="print.css" media="print">❌ Wrong:
<!-- Blocks rendering -->
<link rel="stylesheet" href="large-unused.css">
<!-- Many small files -->
<link rel="stylesheet" href="header.css">
<link rel="stylesheet" href="footer.css">
<link rel="stylesheet" href="sidebar.css">✅ Correct:
<!-- Critical styles inlined -->
<style>/* critical CSS */</style>
<!-- Combined styles -->
<link rel="preload" href="main.css" as="style" onload="this.rel='stylesheet'">CSS loading optimization is critical for performance:
Proper style loading speeds up page display! ⚡