Encapsulation in CSS is a concept that I’ve been mulling over for the past few months now. It is not an extremely difficult idea to grasp, yet more difficult to put into words. What makes it so difficult? Because there are several interrelated concepts that are part of describing the object-oriented approach to design. Likewise, when applying these concepts to CSS (which is not an object-oriented language), there are also interrelated concepts in CSS to describe its key features. I will cover Encapsulation and related matters, the fundamentals of CSS, and how we can apply Encapsulation to CSS using SMACSS and OOCSS.

Encapsulation and Such

Encapsulation

What is Encapsulation? If you investigate it in the wild, you will find that there are several different definitions for this concept. Author Edward V. Berard of the Object Agency lists out several of them in his article Abstraction, Encapsulation, and Information Hiding. In it, he offers the following as the most straightforward definition:

“The concept of encapsulation as used in an object-oriented context is not essentially different from its dictionary definition. It still refers to building a capsule, in the case a conceptual barrier, around some collection of things.[1]”

—[Wirfs-Brock et al, 1990]

So in this sense, Encapsulation is the grouping together of information about an object—or bundling of information[2]. This is the initial understanding of the term that lead me to the conclusion that these concepts apply to SMACSS/OOCSS.


Information Hiding

From the same article:

“... the purpose of [information] hiding is to make inaccessible certain details that should not affect other parts of a system.[3]”

—[Ross et al, 1975]

If we are encapsulating an object (I will define CSS object later), then we aren’t just grouping information about that object together, we are providing that object with some sort of a barrier—literally speaking, that’s what a capsule is! It is this barrier that physically groups the stuff inside it together. So, by that definition, Information Hiding is the protective barrier of Encapsulation that limits or prevents access to the information it encapsulates. However, for the sake of clarity, I am defining them as separate, but highly related notions.

The Cascade, Specificity, and Inheritance

In order to work with CSS and not pull your hair out, you have to have a working knowledge of these fundamental concepts. They are integral to writing out your rules to create the Presentation layer of your design and are key features of CSS as a language.

The Cascade

It should be obvious that the Cascade is the most important concept in CSS (as in Cascading Style Sheets). However, if you read the spec, its definition gets a bit fragmented by examples and explanations. I’m stitching the fragments together here:

“Style sheets may have three different origins: author, user, and user agent. Style sheets from these three origins will overlap in scope, and they interact according to the cascade. The CSS cascade assigns a weight to each style rule. When several rules apply, the one with the greatest weight takes precedence.[4]”

In other words, the Cascade of style rules depends on the origin of the style sheet and the weight assigned to each rule. We are primarily concerned with the author style sheet, but we should be conscious of the other two.


Specificity

As mentioned above, part of how the Cascade works is by assigning weights to each style rule. This weight is described by Specificity[5]. Specificity is based on whether the rule is from the style attribute on an element or from a selector in an internal or external style sheet. Selectors are given different weights based on the type of selector, e.g., universal selectors, ID selectors, class selectors, element selectors, etc. or any combination thereof.


Inheritance

From the working draft, CSS Cascading and Inheritance Level 3:

“Inheritance propagates property values from parent elements to their children.[6]”

This means that values for certain properties can be applied indirectly to nodes in the DOM as they get passed along from parent to child or other descendants. This is important to keep in mind as we build out our CSS because it may lead to rules being written in order to override inherited styles.

Understanding the Cascade, Specificity, and Inheritance is integral to authoring CSS. We will see how these features combine with the concept of Encapsulation in the next section.

Encapsulation In CSS: Putting It All Together

What Is An Object?

In order to understand how Encapsulation can apply to CSS, we should first define what that information is. From the OOCSS FAQ:

“A CSS object consists of four things:

  1. HTML, which can be one or more nodes of the DOM,
  2. CSS declarations about the style of those nodes all of which begin with the class name of the wrapper node
  3. Components like background images and sprites required for display, and
  4. JavaScript behaviors, listeners, or methods associated with the object.[7]”

I will also point out that we have differences of terms—CSS objects and CSS modules. What’s the difference? None, really. Object is an OOCSS term, module is a SMACSS term, but they are meant to describe the same idea. To avoid confusion, I will use object for the remainder of this article.

So, when we talk about Encapsulation strictly in the “bundling of information” sense of the term, this is the information we are bundling to create our capsule—the CSS object.


Bundling in CSS

We bundle information in CSS by keeping our relationships tight between the selector setting the styles and the node receiving them. In SMACSS, this is described as Depth of Applicability.

“The depth of applicability is the number of generations that are affected by a given rule.[8]”

We minimize that depth by authoring classes for the desired rule sets and respecting the Cascade by avoiding the use of descendent selectors from those classes. This prevents any undesired coupling of the CSS to the HTML structure and also keeps our Specificity low. For example, we want to avoid this:


.callout {
  padding: 1em;
}
.callout h3 {
  color: green;
}

If the object grows and contains more <h3>s, we may not want all <h3>s to be the color green—the Cascade would work against us. We would also have to create a selector with a greater Specificity to override it. Alternatively, if the heading for the .callout object must always be the color green and we use an <h4> instead of an <h3>, then the node will not receive { color: green; } and our Encapsulation is broken.

In instances where the HTML structure is more predictable in accordance to the function of that object (e.g., navigation), we can use child selectors for the child nodes. The use of child selectors limits the applicability of the styles only to the children directly associated with the parent providing the styles—tightening the bundle of information.


.nav {
  padding: 1em;
}
.nav > li {
  list-style: none;
}
.nav > li > a {
  display: block;
}

The above example is a reasonable expectation given that we are addressing site navigation. The structure of the HTML is dictated by the function we are trying to serve, making it more predictable.


Information Hiding In CSS

One of the things that I mentioned at the beginning of this article is that CSS is not an object-oriented language—it lacks certain mechanisms for that to be so. More specifically, it lacks a mechanism for information to truly be hidden. By the nature of the Cascade, Specificity, and Inheritance, the information of any node in the DOM is potentially accessible.

For example, if we write the following:

CSS


#l-content p {
  font-size: 16px;
}

.callout {
  padding: 1em;
}
.callout-body {
  font-size: 14px;
}

HTML


<div id="l-content">
  <div class="callout">
    <p class="callout-body">
      Some enticing content.
    </p>
  </div>
</div>

The font-size information in the .callout-body object is not hidden from #l-content p selector due to its Specificity weight (.callout-body=0,0,1,0 vs #l-content p=0,1,0,1). However, avoiding the use of 1.) ID selectors and 2.) descendent selectors we can artificially enforce information hiding of the .callout-body object by limiting access to the font-size information from other selectors.

Information Hiding can also be addressed by Inheritance within the object. Just like in the example above, we can prevent access to the styles of descendant nodes within the .callout object by avoiding properties that pass their values through Inheritance. For example:

CSS


.callout {
  font-size: 14px;
}

HTML


<div class="callout">
  Some more enticing content.
</div>

In this example, all of the descendants of the .callout object would receive { font-size: 14px; } and that information would not be hidden. If we needed to change the font-size, we would have to override those styles—unnecessary additional work.

Conclusion

Hopefully you see how these object-oriented concepts of Encapsulation and related notions are applicable to CSS. Their use can help achieve the overarching goals of SMACSS/OOCSS: styles that are portable, reusable, and scalable. And I’m not alone in this thinking—Kaelig mentions Encapsulation in regards to CSS a couple of times in his article Please Respect the Global CSS Namespace. Furthermore, if you are actively practicing SMACSS/OOCSS, you are already using them! It’s all just a question of shifting your thinking to group these ideas into a neat little bundle.

Cheers!


Footnotes
  1. Berard, Edward V. “Abstraction, Encapsulation, and Information Hiding.” tonymarston.co.uk. Encapsulation. Web. 27 Jun 2013.
  2. “Encapsulation (object-oriented programming).” wikipedia.org. Web. 27 Jun 2013.
  3. Berard, Edward V. “Abstraction, Encapsulation, and Information Hiding.” tonymarston.co.uk. Information Hiding. Web. 27 Jun 2013.
  4. “6 Assigning property values, Cascading, and Inheritance.” w3.org. Section 6.4 The Cascade. Web. 27 Jun 2013.
  5. “6 Assigning property values, Cascading, and Inheritance.” w3.org. Sub-section 6.4.3 Calculating a selector's specificity. Web. 27 Jun 2013.
  6. “CSS Cascading and Inheritance Level 3.” w3.org. Sub-section 4.3.2. Inheritance. 3 Jan 2013. Web. 27 Jun 2013.
  7. “OOCSS.” github.com. FAQ, What is meant by an “object” in OOCSS?. Web. 27 Jun 2013.
  8. “Scalable and Modular Architecture for CSS.” smacss.com. Depth of Applicability. Web. 27 Jun 2013.

Additional References
  1. “Abstraction VS Information Hiding VS Encapsulation.” stackoverflow.com. Questions. Web. 27 Jun 2013.
  2. “Features of OOP.” exforsys.com. 22 Oct 2006. Web. 27 Jun 2013.
  3. “Information hiding.” wikipedia.org. Web. 27 Jun 2013.
  4. “Modular programming.” wikipedia.org. Web. 27 Jun 2013.
  5. Nirosh. “Introduction to Object Oriented Programming Concepts (OOP) and More.” codeproject.com. 25 Jan 2011. Web. 27 Jun 2013.
  6. “Object-oriented programming.” wikipedia.org. Web. 27 Jun 2013.
  7. Richard, Stéphane. “Modular Programming Versus Object Oriented Programming (The Good, The Bad and the Ugly).” petesqbsite.com. Web. 27 Jun 2013.
  8. “Responsibility-driven design.” wikipedia.org. Web. 27 Jun 2013.
  9. Rogers, Wm. Paul. “Encapsulation is not information hiding.” JavaWorld.com. 18 May 2001. Web. 27 Jun 2013.
  10. Yaiser, Michelle. “Object-oriented programming concepts: Encapsulation.” adobe.com. 31 October 2011. Web. 27 Jun 2013.

Sign up to get new posts delivered directly to your inbox!




← Back to Notes