How to Build a Scalable Framework-Agnostic Web SDKs: Step by Step
Italo Menezes | Apr 25, 2025
These days, CSS libraries like Tailwind make creating user interfaces and components easier.
But what happens when things break or behave unexpectedly? Do you know how to fix them?
Understanding the core principles of CSS helps you write more consistent, scalable styles — even when you’re using a framework.
With that in mind, let’s explore the essential principles behind cascading style sheets (CSS).
Let’s start with the basics — how CSS applies styles to HTML elements. Ultimately, a CSS rule is made up of two main parts, the selector and the declaration.
Let’s break it down with a quick example:
The selector is anything before the curly braces ({ }). This targets the HTML element(s) you want to style. In this case, it targets any HTML element with the class “my-class” (identified by a dot .my-class). Selectors can target elements based on class, ID, tag name, attributes, or more advanced relationships.
The declaration block is a set of one or more declarations inside the curly braces. Each declaration includes a property and a value, separated by a colon. In this example, we have three declarations:
Each declaration tells the browser how to style the selected element in a specific way.
Let’s look at color: #115EFB. In this case, color is the property, and #115EFB is the value. Here, the declaration sets the text color to blue.
While this syntax is probably familiar to most developers, it’s an essential structure to understand. Having a strong grasp of this basic CSS anatomy helps with:
Specificity is often the first real stumbling block for developers new (or even experienced) to CSS. If you’re trying to figure out why a button color isn’t applying properly, specificity is most likely to blame.
In CSS, specificity determines which style applies when multiple rules target the same element.
So, if two or more rules conflict, the rule with the more specific selector prevails. Browsers calculate specificity as a weighted score based on selector types.
An ID selector (#) is more specific than a class selector (.), which, in turn, is more specific than an element selector (p, for example).
Additionally, inline styles added directly within HTML elements using the “style” attribute have very high specificity since they directly personalize an HTML element.
Here’s the hierarchy of specificity, from most important to least:
Speaking of importance, there is a way to override this hierarchy — by marking declarations as !important. Let’s look at what that means in the next section.
The term “cascade” in CSS is there for a reason. This might be the most significant, yet often underestimated, CSS rule. Cascading refers to how browsers determine which styles to apply when multiple CSS rules affect the same element.
You might be thinking, “Wait. Wasn’t this covered under specificity?”
While they’re related, cascading considers two additional factors beyond specificity: importance (using !important) and source order (the sequence in which rules appear in your code).
The !important rule was designed to elevate a property’s priority. A declaration marked as !important will override other conflicting rules regardless of specificity (unless another rule also has !important with equal or greater specificity).
For example, p { color: blue !important; } overrides any other conflicting color rule on the same paragraph, even if the other rule has higher specificity.
In practice, developers often use !important when browsers don’t apply expected styles, typically without understanding why.
When it works, it can feel like a relief! However, when even !important doesn’t solve the issue, a deeper investigation becomes necessary. Usually, this type of scenario indicates a loss of control over CSS.
So, use !important carefully — apply it with moderation.
When both importance and specificity are identical, the last rule in the CSS will take precedence. So, if two rules have the same specificity and importance, the one declared later wins.
This also applies to the order of style imports. Stylesheets loaded later override earlier ones. Pretty simple, right?
Summing up, the cascade’s decision-making process involves three main factors (in this order):
If you answered “blue,” congratulations, you’re correct!
Blue applies because the rule #cheesecake { color: blue !important } has higher specificity than .paragraph { color: green !important }. Both have !important, so specificity resolves the tie. Inline styles lose because they’re not marked !important.
Just avoid using !important excessively. While !important can feel like a quick fix when styles aren’t applying how you expect, using it too much leads to problems. If you mark everything as important, ultimately, nothing is important.
Now let’s talk about default styles that browsers apply to HTML elements. Examples include blue, underlined hyperlinks (<a>), bold main headers (<h1>), and automatic indentations for lists (<ul> and <ol>).
These are known as user-agent stylesheets. These defaults offer an initial, semantically coherent visual presentation for unstyled elements, enhancing webpage perception and usability.
However, browser-specific style variations can cause inconsistent webpage appearances.
To ensure things stay consistent, two solutions were created:
CSS Reset removes all default browser styles. This means developers need to define all styling from scratch. Although using CSS Reset is effective, it’s pretty drastic and demands extensive redesign efforts.
With advancements in applications and style sheets themselves (particularly with CSS3), Normalize.css was introduced.
Unlike a reset that eliminates all default browser styles, Normalize.css ensures consistency across browsers while preserving beneficial defaults.
In practice, it ensures elements like headings, paragraphs, and lists render consistently (or very similarly) in modern browsers without removing the basic styles essential for readability.
This is important when writing styles for elements. For example, you don’t need to explicitly define a <div> with display: block or width: 100%, since the browser already applies these styles. After all, a block-level element naturally occupies 100% of the available width.
Most modern CSS frameworks like Tailwind, Bootstrap, and Foundation already include some type of normalization or reset styles out of the box. For example, in Tailwind, Preflight is a version of Normalize.css that also includes tweaks to smooth out cross-browser inconsistencies.
So, even though you don’t need to manually include a separate reset or Normalize stylesheet when using modern frameworks, it’s still important to understand what these default styles are doing, especially if you need to troubleshoot them.
If you want to learn more about default styles, Browser Default Styles is a great resource.
Modern front-end development relies on fast and accurate debugging. And browser Developer Tools are one of the most powerful resources for understanding how your CSS actually works (or not) in the real world. Use these powerful tools to debug your CSS, and you’ll be steps ahead of some of the most seasoned developers who overlook them.
For example, developers can use element inspectors to examine all applied (or overridden) CSS rules, including details on specificity, source order, inheritance, and any !important declarations.
Plus, real-time testing capabilities help streamline adjustments in layout, color, size, and interactions (:hover, :focus, etc.). Mastering this resource means ending guesswork, revealing precisely what happens in your CSS.
Truly understanding CSS fundamentals like specificity, the cascade, and default browser behavior isn’t just about writing cleaner code. It’s about building interfaces that are scalable, predictable, and easier to maintain.
Even with powerful modern tools like Tailwind, CSS Modules, or SASS in your stack, a strong grasp of the fundamentals of CSS will help you debug faster, collaborate better, and keep things consistent. After all, these libraries rely on these core principles, so understanding them is essential.
At Cheesecake Labs, we always choose the right tools for each project. But underneath it all, we know that well-structured, thoughtful CSS is still the foundation of great front-end development.
Whether you’re building a modern CSS framework or starting from scratch, the Cheesecake Labs team can help you design and develop scalable front-end solutions that perform beautifully. Ready to get started? Let’s build something exceptional together.
I love helping people using creative solutions, from design to code. Also I love art, music, outdoors and travel. Pet and Plant father 🥸