REMs and pixels - enjoy the best of both worlds
Tags: css, webpack, css3, tutorial
Published: 2020-06-14 14:38:41

---
title: REMs and pixels - enjoy the best of both worlds
published: true
description: 
tags: css,webpack,css3,tutorial
//cover_image: https://direct_url_to_image.jpg
---

In the frontend teams I have worked in, it is not uncommon for team members to be debating over the use of REMs versus pixels(px) as units of measurement in our CSS.

TL;DR:
- REMs allow for font-sizes across the application to scale according to the user's default browser setting
- However, mockups from designers are typically delivered in pixels and we as developers are accustomed to pixels.

Turns out there is actually an easy solution to this debacle. We can use a PostCSS plugin to convert pixels to REMs in our application build files. Here is an example of how it can be done.

First, we need to set up a starter project with [webpack](https://webpack.js.org/guides/getting-started/).
```shell
mkdir starter
cd starter
npm init -y
npm install webpack webpack-cli --save-dev
mkdir src
touch src/index.js src/style.css webpack.config.js postcss.config.js
```
Your file structure should look like this at this point.
```shell
starter
│───src
│   │───index.js
│   └───style.css
│
│───node_modules       
│───package-lock.json   
│───package.json
│───webpack.config.js 
└───postcss.config.js 
```
Let's add some trival JS and CSS codes.
```javascript
/** src/index.js **/
import "./style.css";

function component() {
  const element = document.createElement("div");
  element.classList.add("hello");
  element.textContent = "HELLO!";
  return element;
}

document.body.appendChild(component());
```
```css
/** src/style.css **/
.hello {
  font-size: 16px;
  width: 16px;
  color: red;
}
```
Now let's add the relevant dev dependancies. We would go into detail what each dependancy does below.
```shell
npm install --save-dev css-loader style-loader postcss-loader postcss-pxtorem
```
[css-loader](https://webpack.js.org/loaders/css-loader/) The css-loader interprets `@import` and `url()` like `import/require()` and will resolve them.
[style-loader] (https://webpack.js.org/loaders/style-loader/) Inject CSS into the DOM.
[postcss-loader](https://webpack.js.org/loaders/postcss-loader/) Loader for webpack to process CSS with PostCSS
[postcss-pxtorem](https://github.com/cuth/postcss-pxtorem/) A plugin for PostCSS that generates rem units from pixel units.

We need to update both `webpack.config.js` and `postcss.config.js` respectively too.
```javascript
/** webpack.config.js **/
const path = require("path");

module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist"),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader", "postcss-loader"],
      },
    ],
  },
};
```
```javascript
/** postcss.config.js **/
module.exports = {
  plugins: [require("postcss-pxtorem")],
};
```
Finally, update `package.json` to add script to build using webpack.
```javascript
/** package.json **/
...
"scripts": {
  "build": "webpack"
}
...
```
Run `npm run build` and you should see a build file `dist/bundle.js`. If you were to inspect `dist/bundle.js`, you would see all pixels notations have been converted to REMs. And there you have it, the debate of pixels versus REMs addressed.

The demo source code can be found [here](https://github.com/kengste/starter).