What should production CSS look like? Share your layout-to-web workflow

jen chan on January 10, 2019

When someone asks you to build a layout in HTML and CSS, how do you approach it? And how do you approach it in a test, versus working for productio... [Read Full]
markdown guide
 
  1. Since mobile development tends to be one, maybe two col max, if I'm only provided a desktop version of the design, I just run with it and simplify/distill the design down. If there's any elements that don't work on mobile, they get cut out completely until the designer complains and sends over a more mobile-friendly design 😁 Unless you're hired as the designer, or you're included in the design process, it's not your job to "get creative" or "invent" solutions to design problems that should have been resolved in the wireframe/mockup phase.

  2. No preference on grid size really. I tend to use 5 and 24 cols, since they're most prevalent in grid systems, but I'll use 3/4/8/16/anything that looks right/makes the design work best.

  3. At minimum for any project, one media query (either for desktop or mobile), and the base CSS defaults to the other. If the design is more complex, I add media queries as necessary to correct issues at the problem breakpoint (usually at uber-wide resolutions if the site's audience is rocking 4k double-wide monitors, or small fixes for absolutely positioned elements)

  4. CSS/SASS for most animations, unless it's so complex that it requires JS (JS functionality like checking animation frames or DOM elements, or using a lib like GreenSock). Going CSS-first usually ensures the highest level of browser compatibility, particularly since animations will work even when JS is disabled client-side.

  5. I use SASS when the project is so large I'll be using variables across the app (which could be replaced with CSS vars) and when I need the power of mixins to simplify CSS generation (like grids, complex animations, or repetitive actions). Otherwise pure CSS run through a minification process (Gulp/Grunt/Webpack/Parcel) before it's deployed to prod works fine. I tend to use BEM combined with OOCSS, so I have non-conflicting CSS styles (.HeaderMenu with .HeaderMenu > .list and .HeaderMenu .item nested classes). That way I get non-conflicting base styles, with without the verbose BEM sub-classes (.HeaderMenu__item) and my shorter CSS classnames work fine thanks to specificity. Similar to Airbnb's CSS style guide (BEM component-style names), combined with Semantic UI's (OOCSS).

 

Thanks for the thorough answers Ryosuke! Re: 5. This is giving me clear insight on why to use SASS. I've given it a half-hearted shot at learning but never felt a personal project of mine needed it. I forgot about mix-ins too, which could be fun. I do enjoy the facility of using minifiers and maybe that is the appeal of preprocessors/CSS libraries. I have also leaned towards using CSS for animations because I heard JS forces the browser to do more work, but never really animated anything that complicated anyway.

 

I don’t use grids from 2015, and bem from 2016. Old good plain css (with some help by postcss) and components based architectures with style-in-component (webcomponents, vue or react doesn’t make difference). The “framework phase” is something that i’ve already saw.

 

Sounds like you feel over grids and frameworks.
What do you enjoy about PostCSS (don't know very much about it) as opposed to the other methodologies mentioned? What kind of projects do you feel they are working well for?

 

I just stopped using css frameworks and methodologies since I started workings with components. I now enjoy the benefit of simple architectures and code maintainability dropping complex systems (and now i can see also useless).

Postcss alone is just a a fast AST parser, the advantages come from the plugins you use. I always start with what i need (3 plugins) and i can make everything. No needs of node-sass, huge dependencies and unused functionalities.

About methodologies, i used BEM for years but with components i don’t need it anymore (it’s is still useful in some contexts).

I think people should just try to drop these 2012 approaches and start trying something that solve today problems.

Could you explain what you mean by "components" outside of what i understand as components in frameworks? I've also read the no-framework thinkpieces out there and while I agree for 90% of hobby horse dev projects frameworks are wayyy too bloated and overkill, I'm at a stage where breadth is helpful for developing experience and a profesh opinion. Also as someone semi proficient in everything libraries help solve a lot of problems beginners can't vanilla js their way out of. Not looking to reinvent the wheel here.

i think mattia is talking about components as in javascript classes or functions that render a single visual component, like you find in react, angular or vue. there are approaches that limit styling and stylesheets to the component level and [nearly] completely throw out the notion of a master stylesheet.

so if you find yourself in the future redesigning the login form, you only have to redesign the login form and not the whole login screen or page or other higher level container. it's essentially BEM, but enforced and maintained by the computer and not a person. it reduces a ton mental overhead and eliminates a whole class of typo/misuse bugs in CSS.

Exactly. But non only with vue/react/svelte etc.. i trust it as mindset. An approach that you can apply even with plain html/css/js and drop the monolithic frameworks approaches that are born many years ago to fix different problems.

Thank you @worc for explaining. Your description makes a lot of sense. I like the idea of writing super lean plain html/css/ vanilla js... but I would need to master JS first. Then would come the question of should I CSS functions or still use SASS? I don't want to be obsessed with rigour but I'm trying to understand what's a professional standard. I'm both studying to "pass the test", but also want to self-improve from what was a previously anti-technical, anti-framework, anti-rigour kind of artistic point of view.

correction: Makes a lot of sense for reusable components/features*, and large scale applications, which I should be gearing up to get used to

Yes. But this approach and mindset can be applied even on small website. Every html elememt and composite block is a "reusable component" by default.

styled-components is a good working example in the react ecosystem. @jen chan, in general, you don't need to use sass if you're building CSS blocks in javascript. javascript gives you access to variables and functions and extensibility natively. it's probably not the best looking syntax around, but i've seen it help a ton in keeping CSS definitions from leaking across components and keeping the scope of a styling problem/solution very narrow.

 

For your specific questions, see below. I'll post another comment for your other points. :)

  1. Sometimes I get mobile designs, sometimes I just have to improvise. Normally though, that improvisation is pretty simple like just re-arranging items. I don't often have to fully switch out interfaces from desktop when going down to mobile. That said, I normally do have a designer I can talk to if I really am not sure about what to do.

  2. Honestly, I don't actually use a grid layout. I have looked at them before but I haven't found one that I'd want to stick with.

  3. I normally have quite a lot of media queries, it probably plays a bit into #2 about why. I write a new media query every time something "breaks" in the layout like if it overflowed off the screen horizontally or wraps in an unusual way. I am aiming for as fluid of a responsive layout as I can. I aim to get breakpoints down as low as 320px.

  4. I use CSS to do all the actual heavy lifting of styling the animation. I will use JS to add/remove classes on a timed sequence if the animation is that complex. The browser can make better use of hardware rendering via CSS transforms etc.

  5. This is going to be an uncommon opinion but I'm not actually a fan of SASS/LESS etc. I do understand what it can provide like removing repetition from CSS and allowing for easier to manage complex styles (eg. variables). That said, I've never hit something with vanilla CSS that I consider a problem that needs a solution like SASS etc. As for BEM, I understand what it can help with but it is too verbose for my liking and I feel makes the styling actually more complicated. I guess these both can be summarized that SASS and BEM solve problems but they don't solve my problems.

 

"SASS and BEM solve problems but they don't" – I feel this way too. Maybe my projects currently doesn't have such a variety of templates/views. I've never had to create something with logins, accounts, dashboards and so many bells and whistles yet. In which case, I really could see scoped or SASS working out. I like the nesting in SASS but it seems counterintuitive to BEM. These kinds of things are confusing and at the moment I guess whatever works doesn't hurt, but I could see it being a leg up in a job app.

 

I've worked on a few big applications in vanilla CSS and while I wouldn't be able to say how it would have turned out with SASS, I didn't really have a problem building it.

Obviously YMMV but I think the approach to take is having clean and concise CSS, broken apart in separate files where it makes sense. This can be achieved without needing something like SASS.

 

I improvise a lot. But I'd like to develop a concise and confident way of going about things. The whole grid thing is relatively new to me as I only used flexbox only before. However recently tried grid with flexbox and some nested grids inside... took much longer but there is way more control.

 

I think a lot about CSS (and programming in general) is finding what works for you. Learning ideas and concepts from others is important but really you are the one that needs to write the code that you need to deal with later. :)

Absolutely. I think after using this for a few years and not quite paying attention to BEM or a lot of CSS frameworks has produced a lot of fomo and confusion, esp trying to get to “industry standard” and it’s time to try a few things to see what sticks. My way has been super detailed base styles or a class per styled element, then media queries for different screen widths. I discover I could be writing a lot less.

I also like the idea of multiple sheets for different components.

 

i come from the Marketing side ( Ad agencies ), my experience may differ from yours if you're working directly with clients.

  1. You should always request a Desktop and Mobile layout at a minimum, if there is no way around it, do your best to adjust and make sure people are aware you're a dev and not designer, so expectations are set. Hopefully by then, they will provide you with the additional layout(s). I don't want to go down the rabbit hole how to design for devs because as a dev, you shouldn't be designing.

  2. I tend to lean into how frameworks create their grids, i normally create a sass mixin to output my columns, 12-grid fluid columns. I would suggest to look at Foundation or maybe Bootstrap. If this is a large project maybe import a framework, if this is a small project i would highly suggest to keep a list of handy mixins you can use in various project.

  3. Everyone should develop smallest-screen-first ( mobile-first ), and should start with two breakpoints, 768px and 1024px. Any additional breakpoints will be dictated by the design.

  4. With animations i would suggest to use GSAP, this animation platform tries to leverage css first but defaults to js. Let's be clear, when you refer to animations i am thinking of non-linear animations, something more then just a fade. Simple rollovers, effects should be in css but the fancy stuff should be with something similar to GSAP. You don't want to add unnecessary weight to your page.

  5. I always use Sass, I like using a process to build my Sass. Most of the current frameworks allow you to add linters, in my current project we are using Gulp, created task to clean, compile, and minified my code.

Not every project is the same, so a one solution approach will not work. Before any project you should start by asking yourself, What tools do i need?, you can use Angular, React, Vue, or even Static Generators like NunJucks. Always have a plan before you build.

 

I've cherry picked a few of your specific points that I can provide opinion on.

apply style using classes with semantic names instead of IDs or elements (i.e. .site_header instead of #header ul)

Yep, a good rule to live by.

include cross-browser prefixes for any animations or exceptions (i.e. for drop-capitals in Safari or webkit- for Safari and moz- for Firefox and ms- for IE. Using an autoprefixer makes that easier.

I've kinda stopped using cross-browser prefixes. The main things I use like transitions, transforms and animations have been long supported. The browsers that don't support them aren't ones I test. That said, it really depends on your target compatibility.

convert any sizes to em and rem instead of px

That is a good rule but sadly not a rule I have been following very much. :(

Write as little to accomplish the most as possible, detailing margin and padding on every little thing makes your styles confusing for someone else to read.

I think the general statement here is good for programming in general. Overly verbose code is always going to have a higher maintenance burden.

To make everything show as the size it should in the design, use *{box-sizing: border-box;}

I agree with wanting box-sizing to be border-box but the way I implement it is a little different.

*, *:before, *:after {
    box-sizing: inherit;
}
html {
    box-sizing: border-box;
}

While not super common, if you did change the box-sizing for a particular element, there is a good chance you want the child elements to behave the same way.

Stay away from inline styling at all costs.

Yep! Even for cases where you might have something like style="display: none;", I'd switch that for a class like .hidden or something.

float as a positioning selector is a thing of the past.

Yep though I'm also bad with this though I am getting better! Flexbox is my go-to instead.

!important does not always fix a problem

Yeah... I've had long discussions with one of my colleagues about !important and whether we should use it at all. Personally, I've tried to avoid !important in any styles at all with the exception of print styles. The only reason I have it there is because of a no-print class I have. Because I target that specific class, other selectors have more specificity so I need to force override them.

 

Thanks for your feedback. By the way, what is this no-print class you mentioned?

 

So a no-print class is designed for controlling whether an element will be printed if someone prints the page. Quite simply, the CSS rule looks like:

.no-print {
    display: none !important;
}

That would be in a print.css file or media query with the media being print.

For me, that is probably one of the only cases where I use !important because that declaration is otherwise not always going to apply.

When you go !important, you need to be absolutely sure that it is the final and ultimate transformation you want to do for matching elements. In print, I need the elements to be gone.

Similarly, you can have only-print classes which do the reverse though it gets harder because for some you might want display: block !important; and others display: flex !important;.

All of this being said, a class like this really is saying what it does rather than what it is, which you may look at as breaking semantic rules for class names.

 
  1. Way too project-dependent to answer. Since space is usually the concern, figure out which elements are essential and which can be relegated to a menu or removed entirely.

  2. I don't use fixed-size grids, it's too restrictive. I do like to have a centered content area of a fixed maximum width, since it's hard to read extremely wide windows.

  3. As few as possible, obviously depends on design and that may not always be possible but I feel it's best to have a single breakpoint around 480px. Why 480? Because your mobile layout will span 300-480 wide and your desktop breakpoint will span 480-800 or 900. You can have a layout that looks good at 480 that's not cramped at 300, you can have a layout that looks good at 500 that doesn't look empty at 800.

    I think it's fine to show/hide a couple of elements with more than one breakpoint too but you don't want to be maintaining 3 or 4 complete separate layouts.

  4. CSS where possible. Not sure where I would have an animation that is only possible with JS. Not counting using JS to change an element's style in order to cause a CSS animation.

  5. SCSS all the time! Here's why a preprocessor like SCSS is indispensable for even small projects:

    • You can manage your theme colors with variables in one spot. If you decide to tweak some colors, makes updating the project super easy. Also makes sure you are staying on-brand and not using a bunch of slightly different shades.
    • You can use mixins for compatibility. Instead of having to write multiple lines of CSS for all vendor prefixes each time you use a single rule, you can write out the prefixes once and be cross-compatible with one line (this is especially handy with css grid)
@mixin select-none {
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

span.cant-select-this {
    @include select-none();
}

Also minification and comments! It's good practice to comment CSS, but I don't necessarily want my comments to be made public. So a preprocessor helps with that too.

 

Great article, thanks, very inspiring!

Those are my thoughts:

  • I would use bootstrap (or similar) only for prototypes or small projects without design specifications, in a big project it becomes a limit in few months (overrides and !important hell)

  • There are auto-prefixers out there, you don’t want to write them manually

  • CSS transition or keyframes (with transform and other hardware acceleration properties) when possible

  • never, ever use IDs for CSS, are unique, in CSS we want to style reusable components, not unique elements :)

  • don’t try to generalise or reuse everything, repetition in CSS is ok, create reusable components, also small ones that includes behavior and style, don’t create reusable classes, there will always be a special case (many actually:) )

  • BEM is a thing, and it’s a good thing to avoid stuff like card sm-margin red in favour of card card—small card—red but also CSS modules and CSS-in-JS are a thing :)

 

Truth be told I recently used initializr when I had to do something super quick for a friend and it was PERFECT. I am not sure why people knock on frameworks.

Oh yes, good point about the auto-prefixers. Going to update that part in the bullet points.

Until today I always thought the best thing about CSS was showing how crazy specific by naming as many direct parent and children and classes as possible. Turns out this is not true! (womp womp)

I only became aware of scoped styles through Vue, though I have yet to build something to such a scale with so many views and templates where it becomes vastly important and convenient. One day.

Just to confirm about ids--so if I wanted to style a "unique" element, I create a different class?

And just to clarify, when you said "create reusable components" instead of classes, you meant that I should decide on what is Block, Element and Modifier (or the look of something in different states) instead of just arbitrarily creating classes for different visual elements right?

 

About ids yes, I would just create a different class.

Create reusable components instead of reusable classes I mean that it’s more clean and elegant, in my opinion, to reuse a component or custom element that encapsulates its own style instead of using the same class on 2 different elements, that I guess it’s the same of scoped CSS in Vuejs

 

I have created Web Atoms Core, which has CSS styling as JavaScript code.

class ListStyle extends AtomStyle {

    public get root(): IStyleDeclaration {
        return {
            color: Colors.gray,
            backgroundColor: Colors.white,
            subclasses: {
                " > li": {
                    color: Colors.blue,
                    subclasses: {
                        " > button": {
                            color: Colors.green
                        }
                    }
                },
            }
        };
    }
}

HTML

<script>
    import ListStyle from "~src/web/styles/ListStyle";
</script>
<ul
    default-style="{ ListStyle }"
    style-class="{ this.controlStyle.root }">
    <li>First Item</li>
    <li>Second Item</li>
    <li>
        Third Item
        <button>Delete</button>
    </li>
</ul>

In order to avoid naming conflicts in CSS, ListStyle class is instantiated once and root property style is given a css name that is unique. When we assign default-style it creates an instance of StyleSheet if it does not exist and attaches style to current component.

Best part is, IStyleDeclaration object is JavaScript object and it can contain any valid javascript and it refreshes when device size changes. You don't need media queries.

class ListStyle extends AtomStyle {

    public screen = (this.styleSheet as AtomTheme).app.screen;

    public get root(): IStyleDeclaration {
        return {
            width: this.screen.screenType === "mobile" ? "250px" : "900px"
        };
    }
}

Styles can be inherited and overridden easily as JavaScript objects. And you don't need to worry about how and where to put in assets. Also style will only be created for the components that are hosted in the page, making browser free of all unused CSS.

 

Hey! These are great thoughts. Totally agree — would also check out AirBnB’s CSS style guide — it’s great.

  1. I’ve never worked on a team with a full time designer! I would agree though, that hamburgers and full screen layouts are usuallly the way to go.

  2. Definitely depends on the design, but I use fr’s a lot. Super helpful for a lot of layouts.

  3. I normally make them once something looks weird. So once text is overlapping or something, I’ll add another mediaquery. I would also look up the sizes of popular devices and make sure your work looks great there.

  4. Normally CSS animations are more efficient than JS ones, but really complex ones can only be done in JS. Transforms specifically go to the GPU which makes them super smooth.

  5. Bem is still a thing a lot of people like and use! I would say SCSS has the market share for preprocessers. Would go in that direction. I use it if it’s easy to set up for the project, if not, it’s not enough of a game changer for me to get it working.

 

I have heard a lot about the AirBnB style guide. And before today BEM seemed just like 1 of 10 million ways to do CSS when I heard about it 2 years ago (and strangely verbose to me), but on another look it seems like a really significant method of component-based styling and also a way to avoid overriding/conflicting styles. I have to go re-read the thing with fr's as far as I understand they do tracking/dividing. laughs nervously

 

I don't worry too much about making nice' CSS anymore.
It is too transient to spend too much time on.
The exception would be if i am trying to really squeeze those last kb's away.

If it works, and wont hamper future progress, like with !important usage, then i'm usually fine with it.

In terms of breakpoints, then i usually tell people to stack it until works.
If you need to squeeze something too much, then you are probably not stacking enough.

Optimally i do this stacking without breakpoints, when i need them i usually use
from this list [375, 480, 768. 1024, 1200].

 

I read about 3%... 2.5% to be honest and kicked this to the read list. But I'll read it when I get 100% sure I can dedicate all of my attention.

As a (mainly) backend developer, I want to give a shout out to all frontend devs. The true magic happens here! Thank you!

 

I know right?! I learn something new talking to devs everyday.

 

I'm subscribed to this because I have more questions than answers, but I'll add some initial thoughts:

Any opinions on using CSS vs JS for animations?

Anything that can maximize hardware acceleration and result in fairly clean code. I feel like these days there are options in both CSS and JavaScript. It's a case by case basis IMO and important to keep using dev tools to keep FPS at 60.

At what point do you see it necessary to use SASS or LESS? Is BEM still a thing?

These preprocessors still seem useful. Even as CSS is gaining more power, SCSS and others are still pleasant to work with. When working with an existing codebase, I'd lean towards running with whatever's in place vs doing new things. BEM definitely still a thing from what I see and here.

Me and CSS:

I feel pretty confident about my ability to write clean CSS in any one place, but don't feel super confident about the general topics outlined here. High level CSS architecture and decision making has alluded me. Thankfully the general idea of not over-architecting it and not doing anything overly hacky and then hoping for the best has been good enough for dev.to to this point, but I'd love if we eventually leveled up our game.

I asked a question here and got a lot of good responses:

It wasn't enough for me to truly commit to any good decisions but it was a lot of helpful food for thought in the discussion.

 

Ok now the only thing i will remember about that is the spaghettis-in-sausage thing.

 

Which, considering the sausage aspect, perfectly described the feeling you get when reading over-done code.

Now, what about this: lesfoodies.com/recettes/saucisse+b...
I'd love to see code that makes me think of such sausages...

 

ha that's cool, and i just ate similar and probably even better sausages i cooked at lunch with romarin. Hehehe. You should make the sausages you crave for. Japanese will be crazy about them !

 

Picking an on-point hero image makes all the difference 💥🍝

 

Just a short one: I've been using SASS for many years, mainly to get variable support and some basic mixins. I'm now considering to try out PostCSS, basically to use brand new CSS features (like e.g. css vars) and transpile them to 'compatible' CSS. Feels more natural to me.

 

// , @jenjchan, dat header picture, whoa, it's the perfect metaphor for so many things.

Where did you find it?

 

I appreciate your appreciation of visually accurate analogies for spaghetti code. I googled "spaghetti CSS" in Google Images. I couldn't find anything satisfactory so I tried "styling spaghetti" and found the perfect pic. It reminded me of Instagram food hacks.

 

// , I'll give this to my colleagues to use when reviewing my code. "Your review can consist of just this picture, and I'll know what you mean."

code of conduct - report abuse