Inverted Triangle CSS (image from http://www.gpmd.co.uk/blog/scalable-css/)
Here’s another great interview / practice podcast that we did. This one is with Table XI front-end developer Aly Fluckey and it’s all about how the Table XI team organizes CSS to best manage the demands of a large code base with lots of styles. We try to avoid common CSS problems, mostly involving having to guess what styles will actually be applied to any given element. The goal is to have the CSS be as predictable and easy to find as possible.
I learned a lot from this interview, and if you work with CSS, I bet you will to. Show notes and transcript after the SoundCloud embed. Thanks to Mandy Moore (http://www.devreps.com) for editing, show notes, and transcript.
02:50 — Implementation
CSS (Cascading Style Sheets)(en.wikipedia.org/wiki/Cascading_Style_Sheets)
08:17 — Grid
A Complete Guide to Grid (css-tricks.com/snippets/css/complete-guide-grid)
10:08 — New Feature Implementation
18:15 — Specificity
ITCSS (Inverted Triangle CSS)
Harry Roberts: Managing CSS Projects with ITCSS (www.youtube.com/watch?v=1OKZOV-iLj4)
26:39 — Putting CSS in Practice; How it Makes Development Easier
NOEL: Hello and welcome to XI to Eye, a podcast series from Table XI. I’m Noel Rappin and today, I’m talking to Aly Fluckey, a UX developer at Table XI.
Aly, do you want to tell us a little bit about what you do and how you got to Table XI?
ALY: Sure. Thanks for having me, too. It’s awesome. It’s my first one, so be nice to me.
I’ve been in software development for almost five years now. I actually started off as a COBOL developer for Nationwide Insurance which is crazy because there was hardly any frontend to that, whatsoever.
NOEL: Are you like the youngest COBOL programmer in the world?
ALY: Probably. I think at Nationwide, I literally was the youngest one that they had on staff in all locations which is pretty interesting.
So, I started off doing COBOL for Nationwide, ended up figuring out that there were newer, more modern languages like Ruby that were pretty fun and eventually took a couple of [inaudible] developer classes actually to learn a little bit more about Ruby. I got into a consultancy in Columbus, Ohio, got offered a Ruby apprenticeship program and I did that for six months. I got hired on as a junior Rails dev and did that for a little over a year before I realized that everything that I loved working on was everything in the browser.
And so, I was lucky enough to be in a position there where they actually helped me pivot from backend developer to frontend developer and paired me with a bunch of other really great frontend and design-type people where I got to learn and ramp up my skills. So, I’ve been doing frontend for exclusively a little over three years now.
I moved here to Chicago about two years ago. I was working as a frontend developer for another consultancy and that’s when I first started learning about Table XI. Last year, I actually worked as a frontend developer for another product company and then when the landscape over there changed and our whole dev team actually lost their jobs, that’s when I actually came over to Table XI, did the full interview process and have been here for just about a year now.
NOEL: Almost exactly a year, I think.
ALY: Yeah exactly, in about a month. It’s crazy. And this is actually the first place that I’ve been where I’m on the design team. Before, I was always kind of the styling person on a backend team or the [inaudible] styling person. So now here, I really love the opportunity that I have to work with other creative like-minded designer-type people and really grow my skill side in other visual and interaction and this overall user experience areas, as well as being able to really grow as a UX developer.
NOEL: On a day-to-day basis, did you do more implementation kind of work, design kind of work?
ALY: I’m mostly on implementation side and I like it that way. I’m that weirdo that loves CSS.
NOEL: Yeah, we’ll be talking about that.
ALY: Fantastic. I went to art school before I became a software developer. I guess I did two years at art school. And I wanted to become a graphic designer. But honestly, I was never really good at being able to get what I see in my head out on paper. Now that I work with people like Rex and Yana who work here on our design team, they are just so much better at getting their thoughts out on to paper and having them be visually aesthetically pleasing. I can speak the design language, if you will, but as far as creating, that is something that I need more practice in.
So, I actually like being on the implementation side and working with designers to make sure that we’re building the thing that they were envisioning when they were thinking about it.
NOEL: Cool. I want to talk more about the implementation part. Table XI has a sort of a unique approach to how it handles frontend implementation and in particular, how it handles CSS, and to a slightly lesser extent, the HTML markup. I wonder if you could talk, first of all, about what kind of problems are really common in large CSS, code structures, I think. A lot of backend developers aren’t really used to thinking of CSS as code or something that needs to be organized until it kind of gets all tangled and they can’t figure anything out. What kinds of problems do you normally see in bodies of CSS code that we try to solve with our sort of general approach?
ALY: First and foremost, to a lot of our applications, since we have a design team, since we have the user experience side of things, we kind of favor custom development over using things like bootstrap or foundation as frameworks. Every once in a while, there will be a situation like in admin panel where we want something that’s going to be able to be built very quickly and without a lot of UX or design attention. So, we’ll actually pull in something like bootstrap or another library to create a theme and then that way, it’s easy to be kind of isolated and contained within and of itself, and then we can have full custom development on the things that we need custom development on. Because one of the things that we run into a lot, if we are in a situation where we pull a library in at the beginning of a project, we might pull in bootstrap or foundation. And in order to make it not look like a bootstrap or a foundation website, you need to do a little bit more customization and overriding of those base library elements.
So then you get into a situation where you have specificity wars where you have big file directories like lots of little files and you never really know where to put something or whether or not you should be overriding a library file or if you should be adding your own component.
NOEL: Does that make it hard to find where to even modify stuff when you want to make changes?
ALY: Absolutely. Then you end up with highly specific elements where we end up having to target the tag under a section header that’s nested under a container or something like that, rather than being like having just [inaudible] classes that we know where to go to look for and we know that it’s not going to be overridden by another file somewhere else in our asset pipeline.
NOEL: Starting with a library and building out your own customizations can make it hard to predict how new markup’s going to behave because you may sort of run into some sort of patch that you don’t know is there?
ALY: Yeah, absolutely. Responsiveness too is a real big area where this happens. We might have to make a font size change at mobile screens. But then you realize that you’re only targeting one specific thing and then you have to add media queries and multiple files and then you never really know exactly where to look for everything happening. That’s another thing that I’ve seen before, too, where we add just like a response of that SCSS at the end of all our style sheets that then handles responsiveness for the entire application when it’s all in one file. Unless you’re actually using the find in your editor to actually specifically find where those things are, it can be very, very difficult.
NOEL: So, that makes it especially hard to predict the behavior of the website at different size of device.
NOEL: What kinds of things do we do to mitigate that? I guess we don’t start with libraries. I know that we have kind of our own custom — framework’s probably a little bit too big to do custom framework. We do have our own custom structure.
ALY: Yeah. One thing that happens and we have the starter repo that we kind of clone all of our new Rails apps from and it has an existing file structure and naming conventions for our style sheets. And then within some of those files, we’ll actually start out with a few base elements, things that kind of rarely change from project to project.
NOEL: So, for example?
ALY: There’ll be something like the layout in container classes as well as the grid. The grid is something that — we have a mixin that actually builds most of our grid classes and then it can be customized to different breakpoints and different widths just by changing some variables. And so, that’s something that can be customized when you’re actually doing the application styling.
NOEL: Is the grid then really — I mean, I don’t do a lot of CSS development. I kind of get to a point where I can hand wave and copy stuff. But the grid is kind of, especially if you’re dealing with responsive multiple sized devices, the grid is critical to making all of that work.
ALY: Absolutely, that’s exactly right. And that’s actually why we’ve tried to standardize on one. And that’s why it’s included in the starter repo is because the current implementation that we have right now is agreed upon within those working as UX developers on projects as being like we all agree upon it right now. It might change in the future, but we like where it’s going and it’s easy for us to reason about. And so, we want to get the overall, like all of the backend developers into a place where they feel comfortable using it too.
NOEL: Is there anything in particular that’s different or unusual about our grid implementation versus bootstrap or foundation’s grid?
ALY: Not so much. In fact, even the naming is pretty close to what you would find in most other library-type grids. I think we just like the fact that it’s really customizable and we don’t have to then rely on an external grid and we can name it whatever we want. So, whatever is working for us right now, we can then tailor it to fit our needs.
NOEL: I think of it as being simpler than some of the implementations I’ve seen.
ALY: The naming, especially the bootstrap grid, has always been confusing to me because it’s like, “What does MD mean?” We actually use full names. So, we use things like medium — 6. And if it’s a 12 column grid, 6 would then be 50%.
NOEL: I’m a big fan of not using abbreviations in variable names all over the place.
ALY: Yeah, absolutely.
NOEL: It seems like you’re saving time but then you just can’t figure out what the thing says.
ALY: Yeah, I just think the cognitive overhead of it is not quite worth it all the time.
NOEL: When you’re working on a new feature, you’re working from specifications that the designer has given you which is usually a mockup in InVision or some other similar tool, correct? What’s your process for turning that into the markup that is the final markup?
ALY: Almost every single one of our applications that we build, we include a living style guide and we actually use a Ruby gem called Hologram for that. And so, usually at the beginning of a project, the designer will kind of get out ahead of development and do some amount of actual visual design. So they’ll do things like pick colors, pick fonts and create a visual system that then is handed off to our UX developers.
NOEL: With like the basic topography and spacing and things like that too?
ALY: Yeah. A lot of times we’ll see things like colors will be included in that, all of the different fonts that we could potentially be using throughout the application will be included, as well as some other like [inaudible] stylings, potentially forms and inputs. Buttons is a big one that is almost always included. And then we’ll take that and we’ll actually build out components within Hologram to have a way to communicate those styles to our backend developers.
NOEL: Can you define component there because I think that’s an unusual concept in CSS design?
ALY: It’s also hard because when I say component, sometimes it means interchangeable things. So, I’ll try and be able to get more specific too.
When we’re building elements within a page — and I actually have a more detailed example if you want to talk about it later — around how we do CSS componentization as like a thing and as a philosophy. And the idea around it is let’s say you have a page that you’re doing articles on and an article has multiple little things within it like a photo and a title and a description. But there are times when we actually don’t want to stroke our styles specifically to that thing.
Like for instance, if it’s an article, we kind of want to make it generic enough that if we have something like a blog post, that styling could then be reused in another situation. Instead of naming it like ‘article’, we might name it something like ‘entry’. And then we’ll create elements within that component. And so, we have like a base component in ‘entry’ and it then contains the photo and the title and the description. And each of those is kind of broken out into individual styles as well.
NOEL: So when you’re laying that out in the code, I know that we build up our directories. So we have one directory for really basic common elements and another directory for components.
NOEL: So you start off and you create a new file for a component and then, do you create a class name that includes all of the other ones? Do you have a bunch of sample class names that are all related by naming convention? Do you depend on the nested behavior of the markup to match the behavior of your CSS?
ALY: Yes. For instance, when we have the — and I actually wrote out a little CodePen example that we can include in the notes and we can kind of follow along here.
NOEL: Yeah, we’ll have a URL for you to look at in the notes.
ALY: Awesome. So we have something like an entry. And so, that would be the block. One other thing, we use the BEM naming convention.
ALY: B-E-M which stands for Block, Element, Modifier.
ALY: We should also include a link there too.
ALY: And at high level is this theory of naming your classes as those kinds of things. So, if you have a block level element that is kind of the container, it’s one thing. That would be like your entry. Or even something like container would be a block level element.
NOEL: So, we have this new component and it’s an entry or an article and so all of our CSS classes that belong to that component would have names that start with entry?
ALY: Yup. For instance, when we add a class to the image for entry, it would be called ‘entry__image’. The __ is actually from the BEM naming convention. And that’s how you differentiate between a block level element and an element and a modifier. So you have blocks, you have elements, and you have modifiers.
NOEL: If you had ‘entry__image’, that indicates that it’s a sub-block.
NOEL: And then we will get an example of a modifier then.
ALY: So that would be something in the CodePen example. I’ve created a modifier for entry that is ‘entry — featured’. And the — is how you know that it’s a modification. We use those in situations where we need to do additional or override a little bit of styling for the base component. So, think of entry as the base component and it has its own set of styles. And then we need to add a special background color for the featured entry. And so that’s when we would actually change the background color under the entry — featured class.
NOEL: So that will be things like highlighted or active?
NOEL: I think the important point about that is that rather than have that be two separate CSS classes like .entry and then also .active, it’s one class called entry — active.
ALY: Yes. And it’s also important to know too that we build modifiers so that they actually add on to the base component. Very rarely are you going to see something that has a class of only the modifier. So, if you ever saw something that was just entry — featured without .entry like the class entry on it as well, that is kind of rare and we tend to not do that.
NOEL: A featured element then would have both the CSS class entry and the CSS class entry — featured rather than just being entry — featured or having entry and then like a generic featured class.
ALY: That’s absolutely right.
NOEL: Is the goal there to prevent naming collisions or to prevent unexpected interactions between different CSS classes throughout the code base?
ALY: Yeah. I think it’s also kind of an artifact from using the BEM naming convention because there’s definitely times when I create a modification then later I realize that there’s enough difference to it, that it actually should be a separate component and that’s all practice and learning experiences.
But it’s one of those things where, for instance, when we have a — container is a really good example of this because we have our .container classes, we’ll have a max width set on them and then also potentially a little bit of padding and those are layout in structural classes. But then we have also a container — type that modifies how much padding is added to the container. But the .container — type without the container class base level on it, won’t get the other styles that are being added like the max width. And so, it’s important to think of these as actual modifications. And then the moment that you have it just a completely separate scenario, that’s a new component.
NOEL: It seems like you don’t really depend on nested CSS a whole lot.
ALY: That’s very true, absolutely.
NOEL: And is that also to prevent surprises, basically?
ALY: Yeah. CSS stands for Cascading Style Sheets. And so therefore, almost everything that we do is actually to battle the cascade which is weird that we’re trying to get around the thing that it actually is supposed to do.
NOEL: That’s interesting. Why is that then?
ALY: Mostly because of specificity issues. Let’s say we have a style written where we have .container and then nested underneath it, we have the tag, the paragraph tag. So that’s going to style all the paragraphs that live within a container different than just a generic paragraph tag that lives without a container. And so then, you run into issues of, again, specificity and not knowing exactly where to change things.
NOEL: You keep saying specificity. I might want a little bit more explicit definition there. It sounds to me like you’re trying to prevent the browser from having to make a choice as to what styles actually get applied to each element. Do you try to make it as explicit as possible?
ALY: Yup. And reduce as much confusion and overriding too. There’ve been definitely times where we open up an inspector and we see on the right hand side, we have all the CSS declarations. If you see a ton of things there crossed out, that’s a pretty good indicator that we have a lot of overriding happening and that’s where you can get into specificity problems where styles are being added that you weren’t expecting.
NOEL: So what would a specificity problem look like in practice? Like what kind of setup would give you that kind of problem?
ALY: Almost every time I’ve had to use bootstrap, I run into specificity problems. Mostly because bootstrap by nature actually does target base level elements like the tag or the tag but scope it to a parent class. You then have to be careful about — you could then have a situation like the container and the tag example from before. If you have one style happening for the that lives inside a container but not happening on the basic paragraph tag, then you can add a paragraph on a page that doesn’t have a container and wonder why it doesn’t have the same styling as the other one on this other page that does live within a container.
NOEL: That can be very hard to check out, I imagine.
ALY: Exactly. So then you end up doing a spelunking exercise through the style sheets trying to find that one paragraph tag that’s adding that one style. And thankfully, the inspector kind of helps with that and it will kind of show you where the file is at potentially sometimes. With Rails, it’s a little bit harder because it manifests everything.
But one way that we combat this is actually through just the way that we organize our files. And this is based off of a methodology called ITCSS which stands for Inverted Triangle CSS. There’s actually a YouTube video where Harry Roberts, the guy who actually thought about all this, gives a presentation and I highly recommend everybody to go watch it.
NOEL: We’ll put that in the notes too.
ALY: Awesome. And basically the way that you can reason about it is the inverted triangle model is actually a really great way to think about it. And at the highest level, at the widest range, you have the things that are most accessible to your entire application. That’s where we put our variables because then as we go down the triangle then the specificity gets increased.
NOEL: So variables will be covering things like background colors, font size.
ALY: Yup. And in the CodePen, I tried to give a pretty good example of some things that we do add variables for — measurements, colors, fonts, things like that. And the way that we think about it is that those variables are then accessible and can be used by any other style sheet that’s in the application, and we want them to be, in fact, that’s why we create variables.
The next level, one level deeper, is like tools. Tools, sometimes, if you’re not using Sass, you may not necessarily be able to use tools. But this is things like functions or mixins or actual pieces of Sass that are building things. This is where we have our grid mixin that builds all of our grid classes. These are things that don’t tend to change a lot and they’re actually not touching any styling parts of the application yet either. With just the variables and the tools directories in your style sheets, nothing in your application should be styled. The moment that we get into actual styling is one level deeper where we do the styling of the base elements.
And so, this is really where we’re only styling the actual elements that exist in the browser, so no classes. This would be things like another list or tag paragraph of all the heading h elements and things like that, table. And we do that so that then you have a basic styling of all of the browser elements that potentially could exist. And this is where we’d actually take the visual style guide that the designers have created and use it to write all the basic styles to live for these base elements. And then it would be we’d create Hologram decorations so that they build out to the Hologram style guide.
NOEL: Right, which everybody can access.
ALY: Yup. And that way, it is a visual tool for everybody who’s building and using the website around how heading elements should look, how inputs should look, how buttons should look without necessarily doing the more specific to the application component styles.
NOEL: Okay. And the next level is the components?
ALY: We actually have a thing in between and that’s where we put our structure which theoretically, you could probably put structure inside components too but we kind of like it to be separate.
NOEL: So, what class do you structure then?
ALY: That would be a grid in our layout like layout is where we keep our container classes, where we set our max width and are kind of like padding.
NOEL: The kinds of things that would go in the elements of the Rails layout to you would be the things around the pattern itself, sidebar footer, that kind of stuff?
ALY: Yes. I could see definitely putting header and sidebar in there too, especially if you have more structural layout things happening. Like for instance, I just recently had to build a header that was actually a sidebar. And so, that required an actual page layout that was a little bit different than how we normally — just like where you have a header at the top, and then you have your main content, then you have a footer. We actually had to do a little bit more of a structural layout that needed to be removed from the actual header component styling, if that makes sense. We needed to build the bones of that first before then we could have the background color of the header and the links that live there.
After structure, then we get into components and that’s everything that’s unique to this project. This changes from app to app too, so it’s kind of hard to say what exactly lives in here. But more than likely, you’ll end up with things like header, footer.
ALY: Forms, definitely.
NOEL: Things would be like articles.
ALY: Yes, entry like in our CodePen example. It would live in components, tags, widget, you can put anything in there. That’s the one that’s a little harder to talk about.
NOEL: Right. I think component is being like something that is a discrete chunk, I can point to it on the screen and say, “This is my component. This is a different component.”
ALY: Yup. And it’s things that we have to write ourselves, too. We think of custom design, that’s a good way to kind of think about it. Whereas an h2 is going to look fairly similar in every browser regardless of — if we don’t add any styling to it, it’s going to look pretty similar across every browser. But these are things that we actually need specific styling that match our styling needs that the designer has set.
And then we actually also include a last folder called utilities. And that’s explicitly for utilities and overrides. So that’s actually a place where you keep helper classes like ‘is warning’ or ‘is hidden’ or ‘is shown’. And it’s the only place that we would ever kind of accept having an exclamation point important.
NOEL: Right, and we have modifiers on our base classes too?
ALY: Yes, exactly. And use our classes, they are the most specific and since they’re included in our application last, they will override anything else that’s happening because of the way that we’ve written everything else. And so that is partially how we get past this specificity problem. We try and make sure that we are organizing all of our elements so that they happen in specificity order and kind of building on the layer above.
I highly recommend watching the video. He also has visual examples that are a little bit easier to reason about than me just talking.
NOEL: Is there something else that you want to say about how this works in practice like how it makes development easier over a long code base?
NOEL: Or some other piece of this that you haven’t talked about that you want to mention?
ALY: I think from the high level, we’ve found success with this simply because it reduces the amounts of questions of like, “Where do I put something?” Or, “Where do I even look for something?” If we know that we’re looking for the styles that happen on an h2 element, then we know we’re going to go to the base directory and look for text or headings or something like that. And if we’re looking for something more specific, we know we’re going to be in the components directory.
The hard part is knowing how generic to make your components, when to create a modification. And the unfortunate thing about that is that there’s no real right answer. I mean, I can go back and I’d look at the apps that I built just even the year ago when I first started here at Table XI and I was making, you could say the wrong decision. But at the time, it was totally right.
And that’s one thing I love about Table XI is that we’re always kind of growing and we’re always using the things that we’ve learned from the last project or the last iteration to get better at the things that we’re working on currently.
So, the way that I wrote something last year is not the way that I write it today and it won’t be the way that I write it next year. And I’m cool with that.
NOEL: Yeah. All the people who do implementation collaborate and share ideas and good practices and pitfalls as they come across them?
ALY: Yeah. We recently started doing retros, specifically [inaudible] like the frontend UX development code and to talk about things like, “Hey, I ran into a weird issue with the grid builder in this one project. How do we account for it?” And so, we’re constantly kind of changing which also, I think, makes it a little difficult because the moment you get a handle on something, it can potentially change. But it does ensure that we’re always moving forward, if you will.
NOEL: Do you have any other resources that people could look for in terms of other generic CSS, if people are just trying to learn CSS things? Places they can go, do you have any to recommend?
ALY: I really enjoy the Learn CSS Layout. It’s actually called LearnLayout.com. It’s got some really great just really quick ways to think about, especially from the ground up. CSS is one of those things that literally is the thing that does structural and also like Sugar. It’s hard to know everything in the middle.
NOEL: Yeah, you don’t want to make your structure out of Sugar or vice versa.
ALY: Exactly. So, knowing the difference between the two and when to use each and how to actually build up from structure to Sugar is an important part of CSS and it’s one of the main things that we focus on here as we’re developing.
I’m trying to think of other great resources. I really like, if people are looking to learn CSS, I recommend Codecademy. It’s got some really great HTML CSS, quick little exercises there. And honestly, if you go to AListApart.com, those people are the ones who are actually writing all of the new CSS specifications, so they know what’s up. From that same group, they have the Book Apart series which I highly recommend and it covers everything from design and user research to actual very technical, like we were talking about today, as far as UX development and frontend code. Just recently, they put out one around SVGs that I’ve been meaning to read. And that’s my main source of information. It’s that group of folks.
NOEL: Cool. Great, good stuff. In that case, thank you, Aly, for talking to me today.
Let me just say that XI to Eye is brought to you by Table XI. We are 35 meticulous and curious minds in Chicago with a 15-year history of building websites, mobile applications, and custom digital experiences for everyone from startups to story brands. Our partners trust us to create innovative solutions that drive their business forward. Let’s work together. Find us at TableXI.com where you can learn more about working with us or working for us.
And you can join us in a couple of weeks for another episode of XI to Eye. Thanks. I’m Noel Rappin.
ALY: And I’m Aly. Yey!
NOEL: Thanks everybody.