# Getting Started

> Part of mCSS (mcss.dev). Rendered page: https://mcss.dev/docs/start

mCSS is both a CSS framework and a methodology. You need to first understand the methodology to use the framework correctly. There are 3 main parts to the methodology.

1. The file structure
1. The CSS syntax
1. The component architecture

Once you've read through the basics below, have a look at the [source code][src] to see how it all comes together, and look at [Installation](/docs/installation) to choose the best option for your project.

## mCSS file structure

<section class="docs_section prose">

### Two folders

**[`framework/`][framework-src]**: the core files you should not edit yourself:

- Settings
- Base
- HTML elements
- Global styles
- Components (optional)
- Themes (the default theme, plus optional swappable themes)
- Helpers

**[`site/`][site-src]**: your own CSS. These files do not use CSS [layers][layers] so **understanding and using [ITCSS][1] methodology there is key**. (The [mCSS own][site-src] `/site` folder is a good reference.)

- Custom theme
- Custom layouts
- Your components
- Page specific overrides
- Patches to vendor plugins, packages, etc.

### The layers

mCSS is a modern take on [ITCSS][1]. Files are organized in [layers][layers] going from broad and generic (settings → reset → HTML elements) to specific and local (components → helpers). This methodology addresses all the supposed "shortcomings" of CSS such as [specificity][3] wars and cascading conflicts.

While ITCSS used specificity for its layers, mCSS upgrades that with native [CSS cascade layers][cascade-layers] priority. Every framework file is imported into a named `@layer`, and the layer order (not the import order, and not specificity) dictates the priority. By default, anything you write _outside_ the layers (in the `/site` folder) has higher priority.

The only exception is [helpers][helpers] which use `!important` to override everything, by design.

Here are all the mCSS layers, from lowest to highest priority:

<div class="docs_oversizedTable">

| Layer           | Files             | What lives there                                |
| --------------- | ----------------- | ----------------------------------------------- |
| `base`          | `base.*`          | Reset/normalize.                                |
| `elements`      | `elements.*`      | Default styling of bare HTML elements.          |
| `global`        | `global.*`        | Grid, wrap, layout scaffolds, prose, a11y.      |
| `components`    | `component.*`     | Self-contained component styles.                |
| `theme.default` | `theme.default.*` | Default [theme][themes] files.                  |
| `theme.user`    | `theme.*`         | Custom theme override.                          |
| `external`      | _(your imports)_  | Code from plugins, npm packages, etc.           |
| `helpers`       | `help.*`          | Tailwind style utility classes, but done right. |
| _(unlayered)_   | your own CSS      | Beats every layer above, except helpers.        |

</div>

Have a look at [`framework/mcss.css`][mcss-entry] to see how it's organized. All layers are _defined_ in this file.

**Notes:**

- `settings.*` files conceptually occupy the top position of the ITCSS "inverted pyramid" with lowest specificity, but since they're only used at build-time, they don't need their own `@layer`.
- The `external` layer ships empty. This layer is reserved for third-party CSS (npm packages, plugins, etc.). That way you can use `@import url(…) layer(external);` to import vendor styles and it becomes trivial to override with your own CSS in a `patch.*` file (like this site's `patch.astro.css`).

### The global import

The global import ([`_global.css`][4] for this site) is where it all comes together. You import everything used on your site there:

- The mCSS framework
- The mCSS components (optional)
- The default theme
- Your theme (optional override)
- Your custom layouts, components, and page overrides
- Vendor style patches

```css
/* global.css */

@import url(./framework/mcss.css);

/* Optional: the mCSS component library. */
@import url(./framework/mcss.components.css);

/* The default theme. */
@import url(./framework/theme.default.css);
/* Optional: your own theme, overriding the default */
@import url(./site/theme.starter.css);

/* Your own CSS: it wins over every mCSS layer (except helpers) */
@import url(./site/global.layout.css);
@import url(./site/component.header.css);
@import url(./site/page.blog.css);
/* etc. */
```

[cascade-layers]: https://developer.mozilla.org/en-US/docs/Web/CSS/@layer
[mcss-entry]: https://github.com/minimaldesign/mCSS/blob/main/src/styles/framework/mcss.css

## Detailed description of all files

<section class="docs_section prose">

### Settings

Two `settings.*` files sit outside the `@layer` stack: they're only used at build time.

- [Media queries][6] include responsive sizes, as well as user preferences like color schemes, reduced motion, etc. See [media queries docs][6].
- **Mixins** (optional). It is not used in other parts of mCSS by default but can be useful to streamline your own components' code. It requires a [PostCSS plugin][7] to work.

### Base

- Simple reset/normalize.

### HTML Elements

The default styling of all HTML elements, without classes.

- **Sectioning:** `header`, `footer`, etc.
- **Text:** `a`, `p`, etc.
- **Quotes:** adds the correct quotes depending on language.
- **Media:** `img`,`video`, etc.
- **Table:** `table`, `th`, etc.
- **Form:** `input`, `button`, etc.
- **Interactive:** `dialog`, `details`.

### Global

Global styles included out of the box:

- A responsive [grid system][grid].
- A full feature [wrapper][wrap].
- Common global site [layouts][layout].
- [Typography][prose], via the `.prose` class, for long form text, like articles, etc.
- [Accessibility][a11y] (A11Y) specific classes.
- Basic `@keyframes` animations (e.g., fade in/out)

### Components

Self-contained styles for single components. mCSS is designed to let you to create your own components, but a [collection of components][components] built on top of mCSS is included. It ships separately to keep mCSS nimble as the component library grows.

**Note:** Some components are CSS-only. A single class on a single element, with no associated HTML. For example, the `.badge` class on a `<span>` is the whole badge, and the `.bt` class can style a `<button>` or an `<a>`.

### Theme

Every design value in mCSS lives in the **default theme** (`theme.default.css`) composed of 2 parts:

- [tokens][5]: Raw design tokens such as dimensions, fonts, colors, etc.
- [UI tokens][uiTokens]: abstraction layer that maps raw tokens to semantic tokens, e.g. `--ui-border-color`, `--input-padding`, etc.

Use the [starter template][srcStarter] to make your own theme (feel free to rename it to anything you'd like but it's recommended to follow the `theme.*.css` convention). Anything you add to this file will automatically override what's in the default theme.

**Don't edit the default theme files:** keeping your design in your theme makes framework updates easy.

If you want to make a self contained mCSS theme you can distribute, see how `theme.wireframe.css` is set up. It basically imports the default theme itself, so you can swap the `@import` in your [global import][4]. More details on that in the [theme docs][themes].

### Helpers

[Helpers][helpers] provide classes for “one-off” local overrides. They're similar to utility classes from other frameworks, with a critical difference: they're meant to be used as a last resort and as sparingly as possible. Helper declarations use `!important` and override everything on that element, including your own CSS. Read [the docs][helpers] for more info on this.

### Your CSS

Your own CSS is unlayered, which means:

- Your CSS has higher priority than mCSS' (except helpers)
- Using the [ITCSS][1] methodology is **critical**.

Your `site/` CSS is required to be imported in this order:

- `theme.starter.css` overrides the default mCSS theme.
- `global.*.css` for site-wide additions to the framework's globals.
- `component.*.css` for your own components (most of your CSS should end up here)
- `page.*.css` for the rare page-specific styles
- `patch.*.css` for patching CSS you don't control, i.e. plugins

**Note:** You can also refer to [mCSS own][4] `/site`'s setup as a reference.

#### Pages

Page files should be used sparingly, for the rare page-specific overrides.

```css
/* page.blog.css */
.blog-index {
  --layout-content-width: 100%;
}
```

**Note**: page classes should go on the `<body>` in the HTML, at the same level as the [layout scaffold](/docs/layout#layouts) classes (not on `<main>`):

```html
<body class="layout layout-centered blog blog-index"></body>
```

## mCSS classes syntax

<section class="docs_section prose">

Classes in mCSS are inspired by [BEM][bem], but they're simpler to use and easier to look at.

You can use standard BEM, the even more verbose [BEMIT][bemit], or any other syntax you'd like. But the mCSS syntax gets you 90% of the same benefits without any drawbacks, even on large projects involving many devs.

Whatever syntax you pick, one rule stands above all of it: **never couple classes across components**. A selector may only contain classes from its own block, and every override goes through classes you mix onto the markup, component tokens, or the theme. It's important enough to have [its own article][coupling], with plenty of examples.

### Blocks, elements, and modifiers

<div class="docs_oversizedTable">

|          | BEM                  | mCSS               |
| -------- | -------------------- | ------------------ |
| Block    | `site-search`        | `siteSearch`       |
| Element  | `site-search__field` | `siteSearch_field` |
| Modifier | `site-search--full`  | `siteSearch-full`  |

</div>

### States

Here's how you implement a state in BEM vs. mCSS.

HTML:

```html
<!-- BEM -->
<form class="form">
  <input class="form__input" type="text" />
  <input class="form__submit form__submit--disabled" type="submit" />
</form>

<!-- mCSS -->
<form class="form">
  <input class="form_input" type="text" />
  <input class="form_submit is-disabled" type="submit" />
</form>
```

CSS:

```css
/* BEM */
.form__submit--disabled {
}

/* mCSS */
.form_submit {
  &.is-disabled {
  }
}
```

**Note:** State selectors have higher specificity than modifier classes (`.avatar.is-online` = `020` vs. `.avatar-xl` = `010`), so always declare custom properties default values inside the main class and _use_ the properties inside the state.

```css
.avatar {
  /* Defaults on the main class */
  --status-dot-size: 12px;

  &.is-online {
    /* ❌ not here: it would override .avatar-xl */
    /* states just use the properties */
    width: var(--status-dot-size);
  }
}

.avatar-xl {
  /* modifiers override the default */
  --status-dot-size: 20px;
}
```

## Components

<section class="docs_section prose">

### Targeting HTML elements within a component

When using mCSS syntax **within a component**, it's considered overkill to create a class for every single HTML element you need to target.

For example, this is acceptable (and recommended) CSS for the [tags][tags] component:

```css
.tags {
  li {
    […]
  }

  a {
    […]
    &:hover {
      […]
    }
  }
}
```

### Modifiers and component variations

When using modifiers to create different variations of a component, it's recommended to use local custom properties if possible instead of overriding the CSS directly. (See the [notice component][notice] for an implementation example.)

```css
/* Don't do that */
.component {
  color: blue;
}

.component-variation {
  color: red;
}

/* Do that instead */
.component {
  --color: blue;
  color: var(--color);
}

.component-variation {
  --color: red;
}
```

### One class per file

<Notice
  type="warning"
  title="This is the most common error I see"
  class="mb-md1"
>
  CSS files must only contain one CSS class, its modifiers, and its elements.
  **Nothing else.**
</Notice>

For example, the `component.card.css` should only contain:

- `.card` and nested HTML elements.
- `.card_*` descendants.
- `.card-*` modifiers.
- State classes
- **Nothing else.** See [this blog article][system-that-scales] for more details.

[1]: /blog/what-is-itcss
[3]: https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
[4]: https://github.com/minimaldesign/mCSS/blob/main/src/styles/_global.css
[5]: /docs/default-theme
[6]: /docs/layout
[7]: https://github.com/postcss/postcss-mixins
[a11y]: /docs/layout#accessibility
[bem]: /blog/what-is-bem
[bemit]: https://csswizardry.com/2015/08/bemit-taking-the-bem-naming-convention-a-step-further/
[components]: /components/start
[coupling]: /blog/component-system-that-scales
[framework-src]: https://github.com/minimaldesign/mCSS/tree/main/src/styles/framework
[srcStarter]: https://github.com/minimaldesign/mCSS/blob/main/src/styles/framework/theme.starter.css
[notice]: https://github.com/minimaldesign/mCSS/blob/main/src/styles/framework/component.notice.css
[grid]: /docs/layout#grid
[helpers]: /docs/helpers
[uiTokens]: /docs/default-theme#ui-tokens
[layers]: /blog/what-is-itcss#the-layers-of-itcss
[layout]: /docs/layout#layouts
[prose]: /docs/layout#prose
[site-src]: https://github.com/minimaldesign/mCSS/tree/main/src/styles/site
[src]: https://github.com/minimaldesign/mCSS/tree/main/src/styles
[system-that-scales]: /blog/component-system-that-scales
[release]: https://github.com/minimaldesign/mCSS/releases/latest
[tags]: https://github.com/minimaldesign/mCSS/blob/main/src/styles/framework/component.tags.css
[themes]: /docs/default-theme
[wrap]: /docs/layout#wrap
