Simple Callout Boxes For Info, TLDR, And So On

Instructions and discussion on building simple, styled callout boxes to add context to article content.

Background

I had a need for simple callout boxes for items like tl;drs, info boxes, etc. I'm using a WYSIWYG editor that I structured into my admin backend views to work on my articles and I don't want to spend a lot of time editing html in the editor. Instead, the solution I came up with was to have designated classes to style the callouts that can be injected using the WYSIWYG user interface. This is a discussion on how I did it.

CSS (SCSS)

The styles are written as SCSS. The callouts are simple enough you could just as easily rewrite them as plain CSS. Anywhere you see a SCSS variable (those beginning with "$"), replace with a CSS variable. Note, you'll need to statically code variables for the background colors evaluated using the Sass color.mix function.

Colors

First, the colors used here were obtained from Bootstrap.

// SCSS Variables
$gray-600: #6c757d;
$cyan:    #0dcaf0;
$green:   #198754;
$yellow:  #ffc107;
$red:     #dc3545;

// Mappings
$secondary: $gray-600;
$info: $cyan;
$success: $green;
$warning: $yellow;
$danger: $red;

Docs for Bootstrap colors.

Even though all my projects have uniquely defined theme colors, I find that these colors for conveying context (warning, danger, etc.) are universally recognized. Therefore, I generally use Bootstrap's colors for components like callouts even though I rarely use the Bootstrap library for projects other than MVPs. I've structured these values as SCSS variables so you can easily swap out colors if you want to play around with them.

Styles

As I mentioned, I'm using SCSS. Primarily this is because I want the color.mix function. But it's not essential given only a few background colors were needed. Using SCSS the styles are formatted with BEM convention. The "block" is the .callout class and the "elements" are the &__icon and &__content children. Last, "modifiers" are used to provide the specific colors for context (info, success, warning, danger).

If you'd rather use plain CSS, simply "un-nest" the rules. For example, .callout {&__icon}} becomes .callout__icon {}. This is how your rendered CSS looks delivered anyway.

Last thing I want to touch on are the modifiers (info, success, and so on). Rather than re-defining the properties for each modifiers, I apply the properties color, border-color, and background-color at the "block" level and pull the values using CSS variables that are created in the modifiers. This follows how you see Bootstrap implement their color schemes. I also use fallback values with the CSS variables so that the user experience isn't too bad if a variable isn't working as expected.

Let's see how this looks implemented.

@use 'sass:color';

$border-radius: 5px;
$shape-width: 5px;
$bg-mix: 95%;
$text-color: #36454f;

// https://getbootstrap.com/docs/5.3/utilities/colors/
$bs-secondary: #6c757d;
$bs-info: #0dcaf0;
$bs-success: #198754;
$bs-warning: #ffc107;
$bs-danger: #dc3545;

.callout {
  display: flex;
  flex-wrap: nowrap;
  gap: 2rem;
  padding: 2rem;
  margin-bottom: 1.5rem;
  max-width: 65ch;
  color: $text-color;
  border: 1px solid;
  border-radius: $border-radius;
  border-color: var(--callout-color, #{$bs-secondary});
  background-color: var(
    --callout-bg,
    #{color.mix(white, $bs-secondary, $bg-mix)}
  );
  position: relative;
  overflow: hidden;

  &::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    width: $shape-width;
    background: var(--callout-color, #{$bs-secondary});
  }

  &__icon {
    flex-shrink: 0;
    width: 25px; // explicit width incase icons are different sizes
    margin-left: $shape-width;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem; // use font-size for icon size
    color: var(--callout-color, #{$bs-secondary});
  }

  &__content {
    flex-grow: 1;
  }

  &--info {
    --callout-color: #{$bs-info};
    --callout-bg: #{color.mix(white, $bs-info, $bg-mix)};
  }

  &--success {
    --callout-color: #{$bs-success};
    --callout-bg: #{color.mix(white, $bs-success, $bg-mix)};
  }

  &--warning {
    --callout-color: #{$bs-warning};
    --callout-bg: #{color.mix(white, $bs-warning, $bg-mix)};
  }

  &--danger {
    --callout-color: #{$bs-danger};
    --callout-bg: #{color.mix(white, $bs-danger, $bg-mix)};
  }
}

Result

Here's a Codepen to illustrate how everything comes together:

See the Pen callout-box by Ian Waldron (@Ian-Waldron) on CodePen.

Final Thoughts

Callouts are a great way to make content pop on the page. What's discussed here is a simple way to implement callouts using SCSS following the BEM method. If you like my approach, give my pen a like and feel free to implement in your project!

Details
Published
June 20, 2024
Next
August 11, 2024

Front-End Practice: Javascript Calculator

Weekend fun with Javascript, CSS & HTML building a functional calculator.