FSM 6: Getting stylish
Welcome to Part 6 of Fresh Start Meteor, a guide that walks you through creating a new Meteor project using ES6, React, Redux, FlowRouter, and Sass. Feeling lost? Start with Part 1.
If you think back to Part 3 when we set up the directory structure, you’ll recall that there’s no official word on how to structure our SCSS. However, by the end of that article we were able to arrive at a fairly robust stylesheet architecture using a modified 7–1 pattern. In this article, we’ll set up all the basic SCSS files we’ll need, given the microapp example we’ve been following so far.
We’ll start in the styles/base/ directory, and create four new files: _normalize.scss, _base.scss, _typography.scss, and _animations.scss.
An aside on partials: If you’re unfamiliar with Sass, the underscores designate that these files are “partials” and should not be compiled into separate CSS files. Instead, we’re going to use a system of includes (like with our JSX) so everything compiles to a single file.
Head over to Nicolas Gallagher’s normalize.css repo and paste his CSS into our new SCSS file of the same name. Normalize is a better alternative to the famous CSS Reset, because rather than wiping all styles it provides a default fallback of standard styles across all browsers. In case something happens to your CSS, Normalize (unlike Reset) will display your page fairly appropriately.
The other three files will remain empty for now, but here’s what to expect:
- base: will contain all default global styles for your project, like for commonly-used HTML elements
- typography: it’s good practice to put all your typography styles in one file, which will help you stay organized and combat both inconsistencies and bloat
- animations: will contain any animation keyframe definitions for use in more than one context
If you want (I highly recommend it, personally), in your _base.scss file, add the following rule to make measurement calculations way easier, described in great detail by Chris Coyier in this article:
html {
box-sizing: border-box;
}
*, *::before, *::after {
box-sizing: inherit;
}
An aside on the double-colon (::): In many tutorials and code examples, you’ll likely see CSS pseudo elements like those above denoted with a single colon (:). Back before CSS3, both pseudo elements (like before and after) and pseudo classes (like hover and focus) were marked by a single colon, but to provide greater clarity the new double-colon was introduced! Please note that pseudo classes still use just one colon.
Now let’s look at the styles/abstracts/ directory, in which we’ll also create four new files: _variables.scss, _placeholders.scss, _mixins.scss, and _functions.scss. We’ll leave all of them empty for now as well, but like before, here’s what to expect:
- variables: Sass variable declarations
- placeholders: Sass placeholder declarations
- mixins: Sass mixin declarations
- functions: Sass function declarations
Duh! If any of these make you scratch your head, check out the official Sass guide.
Neither the elements/ directory nor the vendors/ directory will get any files right now, because we don’t know what elements we’ll have yet, nor do we know what 3rd-party products we’ll end up using.
Setting up imports
In the styles/ directory, create a new _app.scss file. Think of this file like a larger-scale version of those index.js files we made before — making it much easier to manage imports locally and keep development streamlined. Paste in the following code:
@import 'abstracts/variables';
@import 'abstracts/functions';
@import 'abstracts/mixins';
@import 'abstracts/placeholders';// Vendors imports will go here@import 'base/base';
@import 'base/normalize';
@import 'base/typography';
@import 'base/animations';// Elements imports will go here@import '../components/components';@import '../pages/pages';@import '../layouts/layouts';@import 'shame';
As you might have noticed, Sass already knows you’re importing Sass files, so you don’t need to put any annoying “.scss” extensions in each import. Nice!
An aside on Sass load order: you may be wondering why each of these groups is imported in this order, so let me break that down for ya. Since abstracts are where you define your own Sass-specific tools that won’t be compiled to CSS, it makes sense to establish those first so you can use them anywhere. Vendor imports are next, because they come stock and you’ll likely want your own styles to override them.
As we move to base styles, we’re finally getting to CSS that’s yours. We’ll start by normalizing all styles and setting your defaults. The next four sections start super granular and specific and become more general. This allows you to define default styles for each element and component you make first, and then give them context-specific modifications later! I’ll talk about the special _shame.scss file at the end of this article — get excited.
Quiz time: Remember the difference between elements and components from Part 3? It’s okay if you don’t. To refresh your memory: an element is any component that doesn’t have any logic required for its definition (not to say it can’t fire events, but logic isn’t part of the its core definition), whereas components are separately-defined JSX objects that are explicitly imported into context and come with their own default functionality that you (or a 3rd-party developer) defined.
Component, page, and layout styles
You’ll notice that rather than import each component, page, and layout separately into _app.scss, we’re importing a single file for each category. Like with the index.js files in our JSX, this will streamline the process of developing new templates.
Now, let’s make ui/components/_components.scss, ui/pages/_pages.scss and ui/layouts/_layouts.scss files as follows:
_components.scss:
-----
@import 'hello/hello';
@import 'info/info';_pages.scss:
-----
@import 'not-found/not-found';
@import 'welcome/welcome';_layouts.scss:
-----
@import 'application/application';
All that’s left is to make the following (blank) SCSS files:
- ui/components/hello/_hello.scss
- ui/components/info/_info.scss
- ui/pages/not-found/_not-found.scss
- ui/pages/welcome/_welcome.scss
- ui/layouts/application/_application.scss
The shame file
There’s one other special SCSS partial in your imports/ui/styles/ directory, and that is _shame.scss. The concept of the shame file came out of a conversation between web design greats Harry Roberts, Chris Coyier, and Dave Rupert. It’s the perfect place for you to dump the crappy CSS you might write to make a quick fix to a visual bug, or for a hack you implement to nudge something into its right place… because at the time you need to throw something together quickly rather than solve the larger problem.
Since these hacks are often confusing, you should preceed CSS rule you define with a commented description of the problem being bandaged, so you can come back and clean it up later. The goal, obviously, is for this file to be empty, but it’s a great way during the build phase to make quick fixes! I highly recommend using it.
Tell Meteor to compile our styles
First, rename client/main.css to client/main.scss and then insert in the following line to pull all our new stylesheets into a single file for Meteor to compile:
@import '../imports/ui/styles/app';
Codebase check-in
Let’s take a look at your current project architecture. If you’ve been following along so far, here’s what your project should look like:
client/
compatibility/
main.html
main.js
main.scss
imports/
api/
methods/
publications/
startup/
client/
index.js
routes/
index.js
notFoundRoute.jsx
welcomeRoute.jsx
server/
index.js
ui/
components/
_components.scss
hello/
_hello.scss
Hello.jsx
info/
_info.scss
Info.jsx
layouts/
_layouts.scss
application/
_application.scss
ApplicationLayout.jsx
pages/
_pages.scss
not-found/
_not-found.scss
NotFoundPage.jsx
welcome/
_welcome.scss
WelcomePage.jsx
styles/
abstracts/
_functions.scss
_mixins.scss
_placeholders.scss
_variables.scss
base/
_animations.scss
_base.scss
_normalize.scss
_typography.scss
elements/
vendors/
_app.scss
_shame.scss
node_modules/
private/
public/
server/
index.js
tests/
package.json
README.md
PART 7 (COMING SOON): GLOBAL STATE MANAGEMENT WITH REDUX
You can help make this guide better by commenting when anything seems unclear, unhelpful, or plain wrong. Please be clear, detailed, and keep it positive! If you have suggestions for future articles or questions about the guide in general, feel free to tweet at me: @teaganatwater Thanks so much!