Best of Modern Methodology
When I first started out in web development in 2011, I learned it the old way. I learned about keeping my HTML neat and tidy, naming my classes semantically and using specificity in CSS. But the web changed, becoming more complex as time went on and exposing the faults in our best practices. People like Nicole Sullivan, Nicolas Gallagher, Brad Frost, Jeremy Clarke and Jonathan Snook saw how web was starting to demand a different approach and developed new methodologies. In 2013, I started using Nicole Sullivan's OOCSS after reading about it in a chapter of The Smashing Book 4.
I experienced an immediate jump in my efficiency when I started using this method. The principles of modularity and abstraction that it offered made my code infinitely more maintainable and even my speed in initial development went up. However over time, I started to become aware of some problems in the methodology.
One thing led to another, and with my Master's Thesis drawing near, I decided to create an improved methodology. I started out by analyzing CSS' history and modern CSS methodologies - OOCSS, SUIT CSS, Atomic Design, DRY CSS and SMACSS. At the beginning, I planned on simply improving OOCSS - but once my research was done, this approach changed. Almost every methodology I had found had its benefits and drawbacks - so I decided to combine their knowledge and my own realizations into one comprehensive methodology.
This is what Herodotus CSS is.
Herodotus is known as the “Father of History”, as he was the first scholar who researched and combined knowledge from an array of sources. I discovered that this was exactly my approach – to not start from scratch but instead fuse brilliant ideas together.
Different Developers have different workflows. Herodotus CSS introduces an architecture that is meant to be flexible for any developer. It starts with base styles.
Base styles are the foundation of your website. Here, the standard styles of every HTML Tag are written using element selectors. Base styles also include reset styles.
The basis you create here already takes away a bunch of work you would have to do later on and puts it in a easy-to-find box.
The rest of the architecture deals with the tangible parts of a design, starting with layout styles. Layout styles make up the structure of your website, most likely providing a grid layout system. It does not refer to any type of content.
Now let's dive a little deeper into this layout. What we will find is all kinds of content. This content, no matter what kind, is treated in the concept of modularity, as in most other CSS methodologies. However, in Herodotus CSS, Module architecture is split in three.
On the highest level, we have components. These are units of content that serve a clear purpose to the user, whether they are news blocks, carousels, navbars, or simply an image with text next to it. All elements that they contain are defined as subparts of that component and receive their own classes and rules. If you have small variations of a component, feel free to create modifier classes that extend the original component classes. Components can be nested into each other endlessly. This allows you to define broader and broader units of meaning while still preserving the reusability of smaller components. Just be sure to detect smaller ones and create them first before moving on to the bigger picture.
Herodotus CSS goes further than this though. The various visual pieces that make up a component, as well as being subparts, also receive their own clear classification. As far as pieces are visually separate from each other, they are seen as atoms.
This abstraction gives us very reusable, yet overseeable and tangible elements that hook into components, which in turn bend them to fit their needs. However, in order for this to work, they have to follow a couple of rules:
- Atoms have to be condensed. Similar Atoms of one type (e.g. links, buttons or list items) should be distinct from one another in order to prevent too much redundancy.
- Atoms themselves are contextless. They have to be able to hook into any Component, so when you're styling an atom, think of how it would look on its own. It doesn't hurt to look at the rest of the design at this point and spot similar atoms in different places. Condense what you find and apply. The styles that are left are what the specific Component needs to make the atom work! Add that to the component subpart styles.
- The last two points lead up to this one, and it might be hard to grasp at first. Don't worry though, my brain hurt while thinking about it too: Distinct Atoms do not come in variations of their own. That means that modifier classes are dumped for Atoms. Why, you may ask? It seems essential. Well, the whole point of Herodotus CSS is to provide clarity - and Component Subparts are already in charge of Atom modification. If Atoms also had that task, you would have no way of knowing which path to choose when a green link has to be a bit bigger somewhere else. Giving the task to component subparts preserves the independence of Atoms. You might have to repeat a line of code to make that link bigger a couple of times, but you also definitely know where to find that code.
Now all that's missing is the glue that holds everything together. Utilities, unlike layout styles, do not set up a structure, but define a module's spacial relation towards its siblings and parent. They define one single CSS declaration each, making them infinitely reusable. However, in Herodotus CSS, they are tightly controlled, preventing them from overflowing your elements and CSS files. Utility classes are assigned an array of properties that differ the most depending on an element's location. These properties are almost exclusive to utilities. Here's the list:
Remember when I said almost exclusive? Well, in some cases, you may require pixel perfect measurements, i.e. ugly numbers such as "234px". If that is the case, the value is not generally repeatable. Instead, it's most likely that you wrote it for one specific case. So don't hesitate to write those types of declarations into the component they apply to. Also, some of these properties are necessarily shared with your layout styles.
Let's Talk about Names.
What you see below uses a BEM (Block__Element--Modifier) naming flavor that was developed by Nicolas Gallagher.
This part is used to clarify whether a module class refers to a component, an atom or a utility. Components receive the prefix c-, atoms receive the prefix at- and utilities receive the prefix u-.
Any class can be made responsive by adding a mobile prefix. These are usually abbreviations for various screen sizes such as xs-, sm- or md-.
The block segment is a module's main name. Components are named after their functionality, atoms after their element type and utilities after the role that they fulfill.
Child elements of components are named using this segment.
Modifiers have various purposes. In components, they express variations and small class extensions. In utilities and atoms, modifiers are simply used to specify their nature and differentiate elements of the same type.
States contain CSS declarations for behaviors that are modified either during runtime or page generation. In CSS, they are treated like pseudo-classes and receive their own classes. These are then added to whatever class the state applies to, just like :hover or :active.
Now, just combine these building blocks in any way you need them to construct your classes. What you'll get might look something like this:
But again, the way I personally construct my names in detail does not necessarily have to be yours. If you like using CamelCase, go for it. If you'd rather have the spacer utilities be named “margin” at the block level, be my guest. The only thing that is important is that you are consistent and that the prefixes and overall BEM structure are preserved. Also, keep in mind that classes with mobile prefixes are meant to be added to the base class. If you want responsive rules to always apply to a class, just write them directly into it.
With that being said, I did spend time analyzing naming possibilities. What I came up with is a list of name recommendations sorted by priority. It can serve as sort of a guideline if you have trouble naming something. If you're stuck on one type of name, move on to the next in the priority list.
All of the names presented here are examples. For prefixes, you can pretty much use any abbreviation you feel comfortable with. States can be named after the visual or functional state that the element finds itself in.
|Name Segment||Expression Priority List||Examples||Notes|
I didn't find any case where I couldn't name a component after its functionality.
|Name Segment||Expression Priority List||Examples||Notes|
Since atoms on their own are contextless, you shouldn't name them after any sort of functionality.
You can add more modifiers to further specify the atom.
|Name Segment||Expression Priority List||Examples||Notes|
You can add more modifiers to further specify the utility.
Putting it all Together
Now that we have the architecture set up, let's look at how this works in practice. We'll start with the simple example component we set up before and express it in HTML with the applied classes.
As you can see, I've mixed and matched component, atom and utility classes in HTML to achieve my goal. However, I don't need to use everything everywhere. The <h3>-tag doesn't need an atom class because this type of headline can be found in the base styles. It is my default h3. Conceptually, it is still an atom, though.
The <a>-tag on the other hand doesn't have to include a component subpart class because the component doesn't need to change the atom.
The <p>-tag is left completely alone because the base styles are all it needs in this case. Utilities are sprinkled in when necessary to take over the properties that are assigned to them.
So the classes in use already convey a large amount of information to the developer, but aren't too many in number. You can expand on the clarity, though. For instance, I like to head off components with their base class - in the above case, that would be “c-infobox”. While I don't need any special styles here, it tells me where the component begins. Don't overuse this method though, as a lack of classes can also convey information, for example that an element did not need special component styling etc.
So what is visually a component or an atom doesn't necessarily need to be explicitly declared as such within your HTML.
Concerning layout styles, I should mention that they can absolutely be used within your larger elements. A good rule of thumb is that layout styles are applied to containers, e.g. as in grid classes, while utilities are applied directly to components, component subparts and atoms.
So by setting up this architecture, we've formally separated five concepts from each other - base, layout, component, atom and utility styles. Now we're going to transfer this logic to our file structure. We want our CSS files to be short and easy to overview, but also easy to find. We'll begin by creating folders for each category and put components, atoms and utilities in a parent folder named “Modules”.
Let's take it one step further. Sure, now our categories are nicely divided, but we also have multiple types of components, atoms and utilities. In the block segment of their names, that type is defined. So instead of having one long file for components, one for atoms and one for utilities, we will give each type its own file and name it after that type. We should get something like this:
This makes our various elements very easy to find and keeps the individual files short. The flipside of this is that you have to create a new file every time you create a new element type. However, this small amount of extra work pales in comparison to the the time you would otherwise have to spend looking for something.
This is also where preprocessors like SASS and LESS jump in. All of these files couldn't possibly be separate CSS files, the load times would go through the roof and Google would hate you. Instead, let the preprocessor of your choice combine the files into one for you.
At this point, I should mention that while I really would recommend this approach, it's not set in stone. If you prefer to have less files and separate your code in a different way that you find more comfortable, you are entirely free to to do so. The important thing is that you keep a structure that you can navigate through easily.
The Framework Question
Frameworks are useful. There's no denying that. They take away a bunch of legwork from the development process. However, you'll never need every single part of a large framework like Bootstrap. Also, Herodotus CSS naturally isn't applied in any of them. In the end, Herodotus CSS recommends the following:
- If your framework comes in preprocessor files, use them. Then, separate module files from layout or base files and put them into their own folders. This may take some time, but afterwards, you'll never have to do it again.
Now, take the files that you don't use and place them into a folder clearly marked as containing unused styles.
I recommend that you remove all files that have anything to do with modules. This will guarantee a lean and overseeable foundation of layout and base styles to start from.
- If there are any module files that you want to keep, place them into a separate folder inside the “Modules” folder. This way, you can find framework-specific styles more easily.
Some frameworks also come with files dedicated to providing essential variables or a library of mixins. Try to use these conservatively so that you don't have to constantly cross-check them.
Icons don't really fit the bill when it comes to components or atoms. In CSS, they're implemented by using the :before or :after pseudo-classes, which aren't real HTML tags that we can apply classes to. To make matters worse, the type of icon is also controlled via CSS, which is highly variable. At the same time, there is usually a set of rules that determines the icon font family among other things, which is highly static.
All in all, there are two cases of icon use, and each can be solved.
An atom is associated with various different icons throughout the site, each of which shows a very specific function.
An atom is mostly associated with one single icon throughout the site. The icon itself is abstract and applicable in any situation.
These two cases mirror exactly what components and atoms are in charge of respectively. Atoms are meant for general use, so they’re ideally condensed into something a little bit more abstract. Components are in charge of the situational specifics.
This sounds like a perfect fit. However, the static icon code creates an interesting dilemma. If we wrote this code into atoms and components, we’d be repeating ourselves a lot.
In my case, the static icon code looks like this:
So yeah, it's pretty long. However, it’s still better to repeat it than to put it into a separate and reusable class.
This type of extreme abstractification is limited in Herodotus CSS on purpose. In HTML, your class attributes shouldn’t be too verbose and you should be able to quickly tell what classes you need. Icons are visually and conceptually bound to tangible elements, which is why their code, both static and variable, should be found there. It’s simply more natural. Something you can do to save time is stick the static code into a mixin, depending on the preprocessor you use.
To summarize, if an icon within an element changes depending on its context, write all of the icon code into a component subpart class. If the icon stays the same, no matter where the element is placed, write the code into an atom class.
There is a certain case when it comes to atoms where the coding doesn't work out as planned. It's not a particularly rare case either. This occurs when a design element is visually an atom, but needs multiple HTML elements to construct.
If this happens, what you've got is a small component, not an atom. Build the element like you would any other component. The only special thing you need to do is name it appropriately. What I recommend here is to name it after the element type and append “--complex” to distinguish it from its atomic siblings. The result would be something along the lines of “c-button--complex--primary”.
However, if you can, use one HTML element only. Small components should be the exception, not common practice.
Utility Properties in Base Styles
Written text has quite a special place in CSS’ heart. What I am speaking about goes outside the realm of components and into simpler terms - because if we strip away all of the complexity in design that we have today, we are left with writing. Headlines, paragraphs and lists. Even browsers, by default, automatically add margins and paddings to these elements, because they have to fit the flow of text. For these elements, it would be unnatural to disallow utility properties to be written into their base styles.
This doesn’t break the rules of Herodotus CSS - running text is simply different from visual elements.
Psuedo-elements are the second exception. This was something I discovered after already having built the Herodotus CSS website and begrudgingly redacted. If you were to add utility classes that set the margins, padding, etc. of :before and :after elements, you would start seeing an insane amount of verbosity in you class attributes. It wouldn’t make sense to do this, either. Icons, for example, were already declared to be natural parts of their respective atoms or components, so why would the icons’ margins not be? So instead, put the required utility properties where you defined the pseudo-element’s content.
So altogether, there are three cases where utility properties are not exclusive to utility classes:
- Pixel Perfect Measurements
- Elements for Running Text
In the End...
…I created Herodotus CSS to make web development faster, more flexible and more clear - to minimize tedious tasks and let you, the developer, concentrate on the engineering challenges. Currently however, the only person who has used it is me. So please feel free to use it in your project and share it with the community. If you feel that it can be improved upon or that I left something out, please share your thoughts and suggestions with me - I plan to develop Herodotus CSS for a long time.
Angaben gemäß § 5 TMG
Webdesign und Umsetzung von Patrick Santy mit Unterstützung der zeigewas GmbH. Dieses Projekt benutzt außerdem das CSS-Framework Bootstrap.
Haftung für Inhalte
Die Inhalte unserer Seiten wurden mit größter Sorgfalt erstellt. Für die Richtigkeit, Vollständigkeit und Aktualität der Inhalte können wir jedoch keine Gewähr übernehmen. Als Diensteanbieter sind wir gemäß § 7 Abs.1 TMG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 TMG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen. Haftung für Links Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen.
Die durch die Seitenbetreiber erstellten Inhalte und Werke auf diesen Seiten unterliegen dem deutschen Urheberrecht. Die Vervielfältigung, Bearbeitung, Verbreitung und jede Art der Verwertung außerhalb der Grenzen des Urheberrechtes bedürfen der schriftlichen Zustimmung des jeweiligen Autors bzw. Erstellers. Downloads und Kopien dieser Seite sind nur für den privaten, nicht kommerziellen Gebrauch gestattet. Soweit die Inhalte auf dieser Seite nicht vom Betreiber erstellt wurden, werden die Urheberrechte Dritter beachtet. Insbesondere werden Inhalte Dritter als solche gekennzeichnet. Sollten Sie trotzdem auf eine Urheberrechtsverletzung aufmerksam werden, bitten wir um einen entsprechenden Hinweis. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Inhalte umgehend entfernen.
Die Nutzung unserer Webseite ist in der Regel ohne Angabe personenbezogener Daten möglich. Soweit auf unseren Seiten personenbezogene Daten (beispielsweise Name, Anschrift oder eMail-Adressen) erhoben werden, erfolgt dies, soweit möglich, stets auf freiwilliger Basis. Diese Daten werden ohne Ihre ausdrückliche Zustimmung nicht an Dritte weitergegeben. Wir weisen darauf hin, dass die Datenübertragung im Internet (z.B. bei der Kommunikation per E-Mail) Sicherheitslücken aufweisen kann. Ein lückenloser Schutz der Daten vor dem Zugriff durch Dritte ist nicht möglich. Der Nutzung von im Rahmen der Impressumspflicht veröffentlichten Kontaktdaten durch Dritte zur Übersendung von nicht ausdrücklich angeforderter Werbung und Informationsmaterialien wird hiermit ausdrücklich widersprochen. Die Betreiber der Seiten behalten sich ausdrücklich rechtliche Schritte im Falle der unverlangten Zusendung von Werbeinformationen, etwa durch Spam-Mails, vor.
Quelle: Erstellt durch den Impressum-Generator von e-recht24.de für Freiberufler.