DEV Community

Cover image for A guide to using Primer.css
Matt Angelosanto for LogRocket

Posted on • Originally published at blog.logrocket.com

A guide to using Primer.css

Written by Onuorah Bonaventure✏️

Primer.css is the internal framework that GitHub uses to handle styles and organize its CSS. The primary purpose of Primer.css is to enforce consistent styles across a website. In this article, we will learn about Primer.css, how to use it, and what it takes from BEM. We will begin by learning about what it comprises before we build a landing page and evaluate its resemblance to BEM.

Jump ahead:

Getting started with Primer.css

We can install Primer.css via npm or Yarn by running npm install @primer/css. After that, set up Sass and import it into our main SCSS file with the @import "@primer/css/index.scss"; command.

Similarly, you can download the minified version and host it in your code via this link. However, for this article, we will use the CDN version, so make sure to create a new folder named primercss-cdn. Then, create a new index.html file and add the following link to the head tag:

<link href="https://unpkg.com/@primer/css@^20.2.4/dist/primer.css" rel="stylesheet" />
Enter fullscreen mode Exit fullscreen mode

Your code should look similar to this:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
      href="https://unpkg.com/@primer/css@^20.2.4/dist/primer.css"
      rel="stylesheet"
    />
    <title>Primer CSS cdn</title>
  </head>
  <body></body>
</html>
Enter fullscreen mode Exit fullscreen mode

The Primer.css key concepts

Primer.css is a fantastic framework that has been divided into subsections covering utilities, components, and marketing styles. However, we need to understand how breakpoints, spacing, and theming work to get started with the subsections.

Breakpoints and spacing

Like other popular CSS frameworks like Tailwind CSS, Primer.css uses four breakpoints that rely on a min-width property set in the media query. The breakpoints are sm, md, lg and xl which represents a minimum width of 544px, 768px, 1012px, and 1280px.

To specify a breakpoint, you can use a syntax similar to setting the display on a small and medium screen. Primer.css uses a scale from 0-12 that represents values from 0 to 4px, 8px, 16px, 24px, 32px, 40px, 48px, 64px, 80px, 96px, 112px and 128px. To set spacing for an element, you can specify your desired axis like this: <h2 class="px-1 py-1">Content</h2>.

Theming

These days, users have a list of basically two preferences for theming. These preferences are light and dark modes. Primer.css has provided a set of data attributes that can be used to set the theme for your website. These data attributes are expected to be added to the <html> which is the root tag of the entire page. Here’s what they look like:

  • Light theme:

    <html data-color-mode="light" data-light-theme="light">
    <!-- Other tags go in here -->
    </html>
    
  • Dark theme:

    <html data-color-mode="dark" data-dark-theme="dark">
    <!-- Other tags go in here --> 
    </html>
    
  • Dark dimmed:

    <html data-color-mode="dark" data-dark-theme="dark_dimmed">
    <!-- Other tags go in here -->
    </html>
    
  • Dark high contrast:

    <html data-color-mode="dark" data-dark-theme="dark_high_contrast">
    <!-- Other tags go in here -->
    </html>
    

Understanding Primer.css utilities

The Primer.css utility styles include colors, box-shadows, and CSS grids that are used most frequently in our code. Essentially, these styles help us maintain a more consistent style on our website. Primer.css has provided a set of utilities we can use, which we will discuss below.

Padding

Padding is used to specify the internal spacing of an element. Primer.css provides shorthands that can be used together to set padding. For instance, we can set the padding for all the sides of an element in combination with any of the spacing we discussed above like this: p-2. Similarly, we can set the padding for the left, right, top, bottom, vertical, and horizontal axes using the following class names: pl-2, pr-2, pt-2, pb-2, py-2, and px-2.

Primer.css is focused on responsiveness, and staying in line with that goal, the Primer.css team has provided a set of classes for setting the padding for different screen sizes. All you have to do is to attach sm, md, lg, or xl to the padding. It should look similar to this: p-sm-2 py-md-3 pt-lg-4.

Margins and typography

Generally, with margins, we can set the spacing between an element and another element. The class names look very similar to padding except for replacing p with m. Moreover, the class name mx-auto is used to center block elements only when they have a set width while mb-auto, ml-auto, mr-auto and mt-auto are used to move a block element to the top, right, left, and bottom.

It is also important to note that we can set negative margins with class names similar to mr-n6 m-n2 my-n9 my-md-n7. The secret is to precede the letter spacing number with the letter n.

Typography, in this case, includes the styles for setting text alignment, font size, line height, word break, list styles, typographic styles, and more. You can learn more about typography in Primer.css in the official docs.

Text alignment and font utilities

The text alignment utility can be used alight the right, center, or left of the text and images inside an element using the following styles: text-right, text-center, and text-right respectively. Heading and type scale utilities are used to specify the font size of a text or SVG.

The heading utilities set the font size and the font-weight to match the default heading styles. These styles range from h1 to h6 with the former being the largest and the later the smallest:

<p class="h4">I love primer.css</p>
Enter fullscreen mode Exit fullscreen mode

The type scale only sets the font size and ranges from f1 to f6. Here’s an example:

<p class="f5">I love my Life</p>
Enter fullscreen mode Exit fullscreen mode

Colors

Primer.css comes with 13 colors to choose from, including: default, muted, subtle, accent, success, attention, severe, danger, open, closed, done, sponsors, and on.

The CSS classes for setting colors are broadly divided into four parts: text, background, border, and link. The class name for text color is written like this: color-fg-danger. Essentially, the last text can be any of the colors listed above, which includes success, muted, and more.

To use the on text color, it should be written like this: color-fg-on-emphasis. The background color is similar to the text color, as color-bg-subtle. However, it has another deeper color set with emphasis attached to its class name.

Meanwhile, the class name for setting border colors also resembles that of background colors with the following: color-border-open, color-border-closed-emphasis, and color-border-sponsors.

However, Links are a little bit different. It can allow classes for primary, secondary, muted, and states such as hover and nested. The primary link can be written like this:

<a class="Link--primary" href="/home">Link--primary</a>
Enter fullscreen mode Exit fullscreen mode

While the secondary link can be written like this:

<a class="Link--secondary" href="/home">Link--secondary</a>
Enter fullscreen mode Exit fullscreen mode

Muted links can be indicated using the Link--muted class. The on-hover link class is used to make any text color used within the links to turn blue on hover. It can be used like this:

<a class="color-fg-secondary no-underline" href="#url">
 This is a link <span class="Link--onHover">Link--onHover</span>
</a>
Enter fullscreen mode Exit fullscreen mode

Finally, the nested link is used to show emphasis on some text inside a link, as shown below:

<a class="color-fg-secondary no-underline" href="#url">
 This is a link <span class="Link">Link</span>
</a>
Enter fullscreen mode Exit fullscreen mode

Borders

The class names for setting borders are divided into five parts: setting default borders, border style, border radius, border colors, and responsive borders. To set the default border, we can use any of the following class names such as: border, border-left, border-bottom, border-right, border-x, and border-y. Meanwhile, Primer.css allows attaching a scale of 0-3 to the border, such as border-2. It is worth noting that the following class names: border-top-0, border-right-1, border-bottom-2, and border-left-3 can be used to set the border for the edges of an element.

To set the border style of an element, the class name of border must always be provided like this: border dashed. Similarly, we can also provide the border radius of an element using the rounded class name with a scale of 0-3 or the class name of circle to make the element circular. It can be used like this:

<div class="border rounded-2>
 .border .rounded-2
</div>
Enter fullscreen mode Exit fullscreen mode

Or:

<div class="border circle" style="width: 80px; height: 80px;">
.border .circle
</div>
Enter fullscreen mode Exit fullscreen mode

Finally, just like with padding and margin, we can also set the border of an element on different breakpoints. We can do it on any of the border patterns mentioned above, such as: border-sm, border-md, border-lg, border-xl, border-sm-2, border-sm-top, and border-sm-bottom-3.

Box shadows and flex

Primer.css provides five class names to control the box shadow of an element, including: color-shadow-small, color-shadow-medium, color-shadow-large, color-shadow-extra-large, and box-shadow-none.

It can be used as follows:

<div class="color-shadow-extra-large p-3">
  .color-shadow-extra-large
</div>
Enter fullscreen mode Exit fullscreen mode

The class name for handling CSS flexbox essentially reflects what the style does. To make an element a flexbox, we can use d-flex and d-inline-flex which stands for:

{ display: flex; }
Enter fullscreen mode Exit fullscreen mode

And:

 { display: inline-flex; }
Enter fullscreen mode Exit fullscreen mode

Meanwhile, you can use the flex-row, flex-row-reverse, flex-column, and flex-column-reverse classes to set the flex directions. Interestingly, the same naming convention exists for flex-wrap. This means that you can use flex-wrap, flex-nowrap, and flex-wrap-reverse to choose whether flex items should be wrapped into multiple lines when they overflow or into a single line.

It’s worth noting that you should have already made an element a flexbox before you can apply the other flex classes like this:

<div class="border d-flex flex-wrap">
  <span class="p-4 border">Item 1</span>
  <span class="p-4 border">Item 2</span>
  <span class="p-4 border">Item 3</span>
</div>
Enter fullscreen mode Exit fullscreen mode

To apply the justify-content style that is used to distribute the space around and between flex items, we can use the following class names: flex-justify-start, flex-justify-end, flex-justify-center, flex-justify-between, and flex-justify-around.

Furthermore, you can use the following class names to apply the align item style: flex-justify-around, flex-items-end, flex-items-end, flex-items-baseline, and flex-items-stretch.

Although we can create simple and complex layouts using the styles above, there may be times when we want a bit more control over our flex items. The flex-1 class name instructs a flex item to fill up any available space. The flex-auto class can be used to make a flex item fill up open space and auto-resize it if its content changes. While the flex-grow-0 and flex-shrink-0 can be used to prevent the growing and shrinking of a flex item.

Other class names provided by Primer.css are used to adjust the alignment of an individual flex item:

.flex-content-start    { align-content: flex-start; }

.flex-content-end      { align-content: flex-end; }

.flex-content-center   { align-content: center; }

.flex-content-between  { align-content: space-between; }

.flex-content-around   { align-content: space-around; }

.flex-content-stretch  { align-content: stretch; }
Enter fullscreen mode Exit fullscreen mode

And to set the order:

.flex-order-1    { order: 1; }

.flex-order-2    { order: 2; }

.flex-order-none { order: inherit; }
Enter fullscreen mode Exit fullscreen mode

We can even add and apply a responsive style to items by appending any breakpoints to the flexbox class names mentioned above. It generally follows two rules:

  • d-[sm or md or lg or xl]-[the property]
  • flex-[sm or md or lg or xl]-[the property]-[the behavior]

An excellent example of this is setting an item to a flexbox in a particular breakpoint like this: d-md-flex; or specifying justified content style for only a breakpoint: flex-lg-justify-center.

Exploring the Primer.css components

Components in Primer.css are already-built items that look the same regardless of where they are placed on the webpage. They follow patterns that only work when you combine the appropriate modifiers and class names.

Buttons

The Primer.css default button component can be created by adding btn class to a button element, as shown below:

 <button class="btn" type="button">Default button>
Enter fullscreen mode Exit fullscreen mode

Essentially, we can add more classes to a button to set its type, state, and variations. The class names that can be used to specify the button type are btn-primary, btn-outline, and btn-danger. As for the state, we can use the aria-disabled="true" and aria-selected="true" attributes to disable or enable a button. The attributes can be used as follows:

 <button class="btn mr-2" type="button" aria-disabled="true">Disabled
Enter fullscreen mode Exit fullscreen mode

Also, we can specify btn-sm or btn-large to set the size of the button:

  <button class="btn btn-large">Large button</a>
Enter fullscreen mode Exit fullscreen mode

Similarly, we can make a button grow to the width of its parent when we set btn-block class name to it and remove the borders around the button using the btn-invisible class name.

Alerts

Alerts are used to inform users about the status of their actions. In Primer.css, alerts can be created by adding the flash class name to an element. By default, this will generate an alert with a light blue background. However, we can vary the alert by appending the flash-warn, flash-error, or flash-success classes.

Most of the time, alerts are dismissable and have a close button. We can use the flash-close js-flash-close to properly add to it and position the icon for the action. To create the UI of a dismissible alert, your markup should look similar to this:

    <div class="flash mt-3 flash-error">

      Alert message

      <button

        class="flash-close js-flash-close"

        type="button"

        aria-label="Close"

      >

        Close

      </button>

    </div>
Enter fullscreen mode Exit fullscreen mode

Box and Loaders

A Box in Primer.css is a container with a background color, borders, and rounded corners. It has no extra styles by default. To create a Box, we can use the Box class:

<div class="Box">

  Box Content

</div>
Enter fullscreen mode Exit fullscreen mode

A Box can have a header, body, and footer. The following class names can be used to indicate the function of an element inside a box: Box-header, Box-body, and Box-footer. We can use the class name to add emphasis on the title of a Box.

We can use modifiers to further enhance the look and feel of our Box. The Box-header--blue can be used to change the background and border color of an element with the Box-header class name:

<div class="Box">

  <div class="Box-header Box-header--blue">

    <h3 class="Box-title">This is the title</h3>

  </div>

  <div class="Box-body">

  This is  Box body

  </div>

</div>
Enter fullscreen mode Exit fullscreen mode

Other modifiers, such as Box--danger and Box-row--unread can be set to the Box container and the Box item. They essentially add a red border to the Box and a left border to the Box item, respectively.

Loaders are used to indicate a pending state. It should be used with other components and can be triggered using the AnimatedEllipsis class name:

<h2><span>Loading</span><span class="AnimatedEllipsis"></span></h2>
Enter fullscreen mode Exit fullscreen mode

Building a landing page with Primer.css

In this section, we will build a landing page that we can use to demonstrate how to combine components and utilities available in Primer.css. Here is what the result will look like:

Adding a container

The first step in building our landing page is to open the primercss-cdn/index.html that we created earlier. Then, we will create a div that will wrap our app:

  <div style="max-width: 1200px" class="mx-auto py-1 px-2">

  <!-- Content will go here -->

  </div>
Enter fullscreen mode Exit fullscreen mode

Next, we will add our navbar:

      <div>

        <nav class="UnderlineNav" aria-label="Nav bar">

          <div class="UnderlineNav-body">

            <a

              class="UnderlineNav-item app-link"

              href="#home"

              aria-current="page"

              onclick="handleClick(this)"

              >Home</a

            >

            <a

              class="UnderlineNav-item app-link"

              href="#about"

              onclick="handleClick(this)"

              >About</a

            >

            <a

              class="UnderlineNav-item app-link"

              href="#newsletter"

              onclick="handleClick(this)"

              >Newsletter</a

            >

          </div>

          <div class="UnderlineNav-actions">

            <a href="mailto:bonarhyme@gmail.com" class="btn btn-sm">Reach Us</a>

          </div>

        </nav>

      </div>
Enter fullscreen mode Exit fullscreen mode

Let's break it down:

Our navbar is made up of a div that wraps a nav element. The nav contains an UnderlineNav class and wraps two div with an UnderlineNav-body and UnderlineNav-actions that signify two parts of the navbar.

Meanwhile, the UnderlineNav-body contains three a elements that all have the UnderlineNav-item class from Primer.css, app-link class, and aria-current="page" that we will be used to show the currently selected item. Also, each item has an onClick handler, which we will handle with JavaScript.

Adding a hero section

After that, we can add our hero section:

     <div id="hero" class="py-8 blankslate">

        <div

          style="width: 90%; max-height: 200px"

          class="mx-auto border p-3 rounded-2"

        >

          <h1>I love Primer.css</h1>

          <p>Click on the buttons below to find out why:</p>

          <div class="d-flex flex-wrap px-3 my-4" style="gap: 0.5rem">

            <!-- Pop up example -->

            <div class="position-relative text-center">

              <div

                class="Popover position-relative app-popover"

                style="display: none"

              >

                <div

                  class="Popover-message Popover-message--bottom p-4 mx-auto mb-2 text-left Box color-shadow-large"

                >

                  <h4 class="mb-2">Yes, this is the heading</h4>

                  <p>You are not out of luck! This is the message</p>

                  <button

                    type="submit"

                    class="btn btn-outline mt-2 text-bold app-popover-btn"

                    onclick="handlePopover()"

                  >

                    Got it!

                  </button>

                </div>

              </div>

              <button class="btn btn-primary" onclick="handlePopover()">

                View Popup

              </button>

            </div>

            <!-- End Pop up example -->

            <!-- Loading example -->

            <div class="position-relative text-center">

              <div

                class="Popover position-relative app-popover2"

                style="display: none"

              >

                <div

                  class="Popover-message Popover-message--bottom p-4 mx-auto mb-2 text-left Box color-shadow-large"

                >

                  <h2>

                    <span>Loading</span

                    ><span class="AnimatedEllipsis mb-2"></span>

                  </h2>

                 <button

                    type="submit"

                    class="btn btn-outline mt-2 text-bold app-popover-btn"

                    onclick="handlePopover2()"

                  >

                    Got it!

                  </button>

                </div>

              </div>

              <button

                class="btn-mktg btn-small-mktg mx-3"

                type="button"

                onclick="handlePopover2()"

              >

                View Others

              </button>

            </div>

            <!-- End loading example -->

            <!-- Dialog Example -->

            <details

              class="details-reset details-overlay details-overlay-light"

            >

              <summary class="btn" aria-haspopup="dialog">Open dialog</summary>

              <details-dialog

                class="Box Box--overlay d-flex flex-column anim-fade-in fast"

              >

                <div class="Box-header">

                  <button

                    class="Box-btn-octicon btn-octicon float-right"

                    type="button"

                    aria-label="Close dialog"

                    data-close-dialog

                  >

                    <!-- <%= octicon "x" %> -->

                    <svg

                      class="octicon octicon-x"

                      viewBox="0 0 12 16"

                      version="1.1"

                      width="12"

                      height="16"

                      aria-hidden="true"

                    >

                      <path

                        fill-rule="evenodd"

                        d="M7.48 8l3.75 3.75-1.48 1.48L6 9.48l-3.75 3.75-1.48-1.48L4.52 8 .77 4.25l1.48-1.48L6 6.52l3.75-3.75 1.48 1.48L7.48 8z"

                      </path>

                    </svg>

                  </button>

                  <h3 class="Box-title">What do you think about this?</h3>

                </div>

                <div class="overflow-auto">

                  <div class="Box-body overflow-auto">

                    <p>

                      You see how cool this CSS framework is??

                      <br />

                      It is what it is!

                    </p>

                  </div>

                  <ul>

                    <li class="Box-row">

                      <img

                        class="avatar v-align-middle mr-2"

                        src="https://avatars.githubusercontent.com/bonarhyme?s=48"

                        alt="bonarhyme"

                        width="24"

                        height="24"

                      />

                      @bonarhyme

                    </li>

                    <li class="Box-row border-bottom">

                      <img

                        class="avatar v-align-middle mr-2"

                        src="https://avatars.githubusercontent.com/bonarhyme?s=48"

                        alt="bonarhyme"

                        width="24"

                        height="24"

                      />

                      @bonarhyme

                    </li>

                    <li class="Box-row border-bottom">

                      <img

                        class="avatar v-align-middle mr-2"

                        src="https://avatars.githubusercontent.com/bonarhyme?s=48"

                        alt="bonarhyme"

                        width="24"

                        height="24"

                      />

                      @bonarhyme

                    </li>

                  </ul>

                </div>

                <div class="Box-footer">

                  <button type="button" class="btn btn-block" data-close-dialog>

                    Close

                  </button>

                </div>

              </details-dialog>

            </details>

            <!-- End of Dialog example -->

          </div>

        </div>

      </div>
Enter fullscreen mode Exit fullscreen mode

Let's break it down:

The hero page is made up of a div that contains a hero ID and py-8 blankslate class names. It wraps around another div with the following styles and class names:

  style="width: 90%; max-height: 200px"

  class="mx-auto border p-3 rounded-2"
Enter fullscreen mode Exit fullscreen mode

The inner div contains an h1, p, and a div with the following style and classes:

 class="d-flex flex-wrap px-3 my-4"

 style="gap: 0.5rem"
Enter fullscreen mode Exit fullscreen mode

Inside the div we have a popup, loading, and dialog example. The secret to creating a popup with Primer.css is adding the position-relative text-center class to the element you want to make a popup. Then, it should have the div and button children that will be used to display the contents and trigger the popup. For our example, our button should have the following attributes:

 class="btn btn-primary"

 onclick="handlePopover()"
Enter fullscreen mode Exit fullscreen mode

The div containing the content should have the following attributes:

  class="Popover position-relative app-popover"

  style="display: none"
Enter fullscreen mode Exit fullscreen mode

It should also have an inner div of the classes: Popover-message Popover-message--bottom p-4 mx-auto mb-2 text-left Box color-shadow-large that will eventually contain the contents. We can also add an onclick to a button inside the Popover-message with onclick="handlePopover()".

Creating the sections

Next, we will add the about us section to our landing page. The about section contains an h2 that is actually a tooltip. It also includes another div with a colorful timeline with four items in it. For brevity, here’s the link to the GitHub repo.

The first timeline item contains breadcrumbs. While the second, third, and fourth timelines have truncated links, normal links with a hover state style, and a toast component.

Next, we have the newsletter section which we can add with the following:

     <div id="newsletter">

        <h2 class="py-2 h3-mktg">Subscribe to my Newsletter</h2>

        <form>

          <div class="form-group">

            <div class="form-group-header">

              <label for="example-text">Email address</label>

            </div>

            <div class="form-group-body">

              <input

                class="form-control"

                type="text"

                placeholder="Email address"

                id="example-text"

              />

            </div>

          </div>

          <button class="btn btn-block btn-primary" style="max-width: 440px">

            Submit

          </button>

        </form>

      </div>
Enter fullscreen mode Exit fullscreen mode

Let's break it down. The newsletter section contains an h2 and a form. The form contains a label, input, and a button. Next, we have the footer, as shown below:

  <div>

    <p class="text-center py-4">

      Made by

      <a href="https://github.com/bonarhyme">bonarhyme</a>

    </p>

  </div>
Enter fullscreen mode Exit fullscreen mode

Finally, we have our script that handles onclick events in our code:

// Internal JavaScript written inside the body of HTML

    <script>

      function handleClick(e) {

        document.querySelectorAll('.app-link').forEach((x) => {

          x.removeAttribute('aria-current');

        });

        e.setAttribute('aria-current', 'page');

      }

      function handlePopover() {

        const popup = document.querySelector('.app-popover');

        if (popup.style.display === 'none') {

          popup.style.display = 'block';

        } else {

          popup.style.display = 'none';

        }

      }

      function handlePopover2() {

        const popup = document.querySelector('.app-popover2');

        if (popup.style.display === 'none') {

          popup.style.display = 'block';

        } else {

          popup.style.display = 'none';

        }

      }

    </script>
Enter fullscreen mode Exit fullscreen mode

What does Primer.css take from BEM?

Primer.css has a unique architecture that uses object-oriented CSS programming techniques and is influenced by the BEM model. BEM stands for block, element, and modifiers. Essentially, BEM is a method of writing CSS and structuring HTML that helps create components that are cleaner and easier to share across the team. To learn more about BEM and its methodologies, check out this article.

Generally, a block is a standalone entity or component that stands and is meaningful on its own. A great example of a block is a menu, navigation, box, and so on. It should be written like this:

<div class=”card”>

<!-- elements and modifiers go here –>

</div>
Enter fullscreen mode Exit fullscreen mode

An element is part of a block semantically tied to its block. Mostly, it has no standalone meaning and should always be tied to a block. Navigation items, box headers, and menu items are all great examples of an element. It can be written with double underscore like so:

<div class="navigation__item">A navigation item</div>
Enter fullscreen mode Exit fullscreen mode

Or like this:

<div class="card__header">This is a card header</div>
Enter fullscreen mode Exit fullscreen mode

As the name implies, a modifier is used to change the behavior and appearance of a block or an element. This means that a modifier can be tied directly to a block or an element. Examples of applying a modifier to a block include: navigation disabled, box danger, button large, etc. An example of appending a modifier to an element includes: navigation item disabled, box header danger, and more. Generally, a modifier should be written like this:

<div class=”card__button–danger”>A card button that indicates an error that has occurred</div>
Enter fullscreen mode Exit fullscreen mode

Furthermore, The syntax for writing BEM using a card as an example is as follows:

 <section class="card">

      <h1 class="card__title">The Title</h1>

      <div class="card__imageContainer">

 <img src="https://images.unsplash.com/photo-1676136358787-6510632d3e30?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=387&q=80"

          alt="an amazing landscape"

          class="card__image"

        />

      </div>

      <div class="card__content">

       <p class="card__description">

          Lorem ipsum dolor sit amet consectetur adipiscing elit. Aperiam porro

          quidem iure natus consequatur. A dolorum quis mollitia veritatis

          nostrum excepturi eligendi impedit doloremque, autem non reiciendis

          nemo, error quidem.

        </p>

        <div class="card__buttonGroup">

          <button class="card__button">Proceed</button>

          <button class="card__button card__button--disabled">Cancel</button>

          <button class="card__button card__button--danger">Delete</button>

        </div>

      </div>

    </section>
Enter fullscreen mode Exit fullscreen mode

And CSS:

.card {

        width: 100%;

        max-width: 400px;

        margin-left: auto;

        margin-right: auto;

        border: 1px solid gray;

        padding: 0.8rem;

        border-radius: 0.5rem;

      }

      .card__title {

        color: rgb(31, 31, 31);

      }

      .card__imageContainer {

        width: 100%;

        height: 300px;

      }

      .card__image {

        width: 100%;

        height: 100%;

        object-fit: cover;

      }

      .card__buttonGroup {

        display: flex;

        gap: 0.5rem;

      }

      .card__button {

        padding: 0.4rem 0.8rem;

        cursor: pointer;

        outline: none;

        border-radius: 0.3rem;

        border: 1px solid;

      }

      .card__button--disabled {

        cursor: not-allowed;

        background-color: gray;

        border-color: gray;

      }

      .card__button--danger {

        background-color: rgb(231, 36, 36);

        color: white;

        border-color: rgb(231, 36, 36);

      }
Enter fullscreen mode Exit fullscreen mode

How Primer.css is different

Primer.css makes use of the same pattern BEM uses. However, instead of double underscores, which are used to identify elements, it uses a hyphen. But for modifiers, it makes use of an ARIA for button components and a double hyphen for some other components, like a Box.

A block in Primer.css includes components such as Dropdowns, Pagination, Popovers, and menu. It should be noted that some blocks are capitalized while some are lowercase. With BEM, elements shouldn't be standalone and should instead be inside of a block. The same applies to Primer.css; an element must be inside a component to work as expected. Also, modifiers must be combined with a block or an element to work correctly.

BEM methodology ensures that our CSS code is more structured and easily reused across the team in various application parts by enforcing a more consistent pattern of generating class names. This particular approach is what Primer.css uses under the hood to ensure that our app UI is consistent across the board.

Conclusion

The simplicity of Primer.css makes it an excellent choice for building your next project and should be adopted because it comes with many components and utilities that are very responsive and clean. Thank you for reading through. I hope you enjoyed this article, and be sure to comment if you have any questions. Happy coding!


Is your frontend hogging your users' CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.

LogRocket Dashboard Free Trial Banner

LogRocket is like a DVR for web apps, recording everything that happens in your web app or site. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web apps — Start monitoring for free.

Top comments (0)