Components

Use oo-component to group recurring styling.

Loop semantic offers separation of concerns to differentiate components from other styling and to facilitate readibility. The HTML becomes easier to understand and to maintain while lightening the class attribute which can be too often overcrowded (A class with a component name along with a list of modifiers + a bunch of unrelated utilities).

By default, Loop components are used without the data attribute to remove verbosity and to get a shorter name for speed purposes oo-componentName. You may turn on the option dataAttr to be a fully-valid HTML attribute.

@include ooCreate((
  dataAttr: false, // default oo-componentName
));
<!-- Column component -->
<div oo-row="align-center gutter-less" class="font-small text-center">
  <div oo-col="span12 span3@sm"></div>
  <div oo-col="span3@sm"></div>
  <div oo-col="span3@sm"></div>
</div>

Loop components

Custom components


# Custom components

Loop gives you the possibilty to create your own Loop syntax component. That offers you an alternative to regular css in the case of making a recurring style along with numerous modifiers.

Example of a situation

I created a reusable component for all the diverse messages of my project. I named it .notification and namespaced each modifiers with it. I'm happy as it is extremely understandable.

<!-- Notification component -->
<div class="notification notification-success notification-large notification-centered">
  <strong>Hey, well done!</strong><br>You've created a <i>success</i> notification component
</div>
Hey, well done!
You've created a success notification component.

It's a bit redundant. So I refactored the modifiers' logic by using keywords such as is which I am using for utilities as well. I'm very happy as it is still extremely understandable with less writing.

<!-- Notification component with shorter modifier -->
<div class="notification is-success is-large is-centered">
  <strong>Hey, well done!</strong><br>You've created a <i>success</i> notification component.
</div>

In the case where I'm adding utilities, the class attribute gets crowded, making it harder to know what's going on at a glance. I sometimes get confused between the modifiers and the utilities.

<!-- Notification component along with utilities -->
<div class="notification is-success is-large is-centered has-font-italic is-float-left is-hidden-print">
  <strong>Hey, well done!</strong><br>You've created a <i>success</i> notification component.
</div>

I refactored my component again using Loop syntax. I'm extremely happy with the separation of concerns as I know what does what as well as avoiding redundant text.

<!-- Loop Notification component with Loop utilities -->
<div oo-notification="success large centered" class="font-italic float-left hidden@print">
  <strong>Hey, well done!</strong><br>You've created a <i>success</i> notification component.
</div>

# Create from config

Pass css properties to props and to the variants name as a map value.

$ooLoop: ooAdd('components', (
  'notification': (
    props: (
      padding: 1rem,
      border-left-width: 5px,
      border-left-style: solid,
      box-shadow: 4px 4px 8px rgba(0, 0, 0, .15),
    ),
    variants: (
      'success': (
        color: #015a31,
        border-color: #83cca9,
        background-color: #c8f7e1,
      )
      'danger': (
        color: #5a0101,
        border-color: #ca7878,
        background-color: #f7c8c8,
      ),
      'large': (
        padding: 1.75rem 2rem,
        font-size: 1.5rem,
      ),
      'centered': (
        text-align: center,
        border-left: 0,
        border-top-width: 5px,
        border-top-style: solid,
      )
    )
  ),
));
<div oo-notification="danger centered">
  <strong>Hey, well done!</strong><br>You've created a <i>danger</i> notification component.
</div>
Hey, well done!
You've created a danger notification component.

Target children elements

Use > as a property name within the list of CSS properties to target nested elements. Then, define a map of CSS selector with CSS properties.

$ooLoop: ooAdd('components', (
  'notification': (
    props: (
      padding: 1rem,
      border-left-width: 5px,
      border-left-style: solid,
      box-shadow: 4px 4px 8px rgba(0, 0, 0, .15),
      '>': (
        'strong': (
          text-transform: uppercase,
          font-size: 1.1em,
        )
      )
    ),
    variants: (...)
  ),
));
<div oo-notification="danger centered">
  <strong>Hey, well done!</strong><br>You've created a <i>danger</i> notification component.
</div>
Hey, well done!
You've created a danger notification component.

Target pseudo-elements

Use before and after as property name and assign a map of CSS properties as value.

$ooLoop: ooAdd('components', (
  'notification': (
    props: (
      ...,
      '::before' : (
        margin-left: 10px,
        float: right,
        width: 22px,
        height: 22px,
        color: #fff,
        text-align: center,
        border-radius: 50%,
      ),
    ),
    variants: (
      'success': (
        color: #015a31,
        border-color: #83cca9,
        background-color: #c8f7e1,
        '::before': (
          content: '\2713',
          background-color: #4ea97d,
        )
      )
    )
  ),
));
<div oo-notification="success">
  <strong>Hey, well done!</strong><br>You've created a <i>success</i> notification component.
</div>
Hey, well done!
You've created a success notification component.

# Creation from mixin

Combine the two mixins ooComponent() and ooComponentVariant() and develop your own Loop component after the initialization of the Loop config.

ooComponent($name){ @content }

Mixin - Create a base component

  • $name (string) The name of the component
  • @content CSS rules
@include ooComponent('notification') {
  padding: 1rem;
  border-left-width: 5px;
  border-left-style: solid;
  box-shadow: 4px 4px 8px rgba(0, 0, 0, .15);
}

ooComponentVariant($componentName, $variantName){ @content }

Mixin - Create a component variation

  • $componentName (string) The name of the component
  • $variantName (string) The name of the variant
  • @content CSS rules
@include ooComponentVariant('notification', 'success') {
  color: #015a31;
  border-color: #83cca9;
  background-color: #c8f7e1;
}
@include ooComponentVariant('notification', 'danger') {
  color: #5a0101;
  border-color: #ca7878;
  background-color: #f7c8c8;
}
@include ooComponentVariant('notification', 'large') {
  padding: 1.75rem 2rem;
  font-size: 1.5rem;
  strong {
    font-weight: 900;
    text-transform: uppercase;
    letter-spacing: -.5px;
  }
}
@include ooComponentVariant('notification', 'centered') {
  text-align: center;
  border-left: 0;
  border-top-width: 5px;
  border-top-style: solid;
}
<div oo-notification="success large">
  <strong>Hey, well done!</strong><br>You've created a <i>success</i> notification component
</div>
Hey, well done!
You've created a success notification component.
<div oo-notification="danger">
  <strong>Hey, well done!</strong><br>You've created a <i>danger</i> notification component.
</div>
Hey, well done!
You've created a danger notification component.

# Turn Utility First Component into Loop Component

Developing with utilities increases speed and help us prototyping rapidly custom components. As a result, we tend to add an incredible amount of single classes to a single html element to achieve a specific style. Repeating the same classes while making reusable modular code could easily start to be unproductive.

Take into condiseration setting aside utility-first-component for common group paterns and turn them into loop-component. Write less HTML with more CSS.

Example with the Event utility-first

17 classes + 1 button component & 2 modifiers

<div class="bg-white text-center shape-squircle overflow-hidden shadow-tiny">
  <time datetime="2020-09-07 10:00"
    class="d-block wrapper-tiny bg-primary color-white font-small text-uppercase">
    September 7th, 10am
  </time>
  <div class="wrapper-small wrapper-medium@md">
    <h3 class="mt-0 mb-0">Frontend Developer Festival</h3>
    <p class="text-wide">Tokyo, Odaiba, Big Sight</p>
    <button class="shape-stadium" data-oo-button="primary outline">Join</button>
  </div>
</div>

Frontend Developer Festival

Tokyo, Odaiba, Big Sight

Make Event loop-component

// _config.scss
@import 'oo-loop/loop';

$ooLoop: ooSet('palette.alert': #f15f63);
$ooLoop: ooSet('button.outline', true);
$ooLoop: ooSet('button.variants.stadium', (
  border-radius: 50em,
);

$ooLoop: ooSet('components', ('event': (
  props: (
    padding: (
      rt: 1rem,
      sm: 1.5rem,
    ),
    overflow: hidden,
    text-align: center,
    background-color: #fff,
    border-radius: 1em,
    box-shadow: 0 1px 1px 0 rgba(0,0,0, .15),
    '>': (
      'time': (
        padding: .5rem,
        margin: (
          rt: -1rem -1rem 1rem,
          sm: -1.5rem -1.5rem 1.5rem,
        ),
        display: block,
        color:#fff,
        font-size: rem(14),
        text-transform: uppercase,
        background-color: this('palette.primary'),
      ),
      'h3': (
        margin: 0,
      ),
      'p': (
        letter-spacing: .5px,
      ),
    ),
  ),
  variants: (
    'alert': (
      '>': (
        'time': (
          background-color: this('palette.alert')
        ),
        'h3::before': (
          margin-bottom: 4px,
          display: block,
          content: '!!!Cancelled!!!',
          font-size: 1rem,
          color: this('palette.alert')
        )
      )
    )
  ),
)));

@include ooCreate();
<div oo-event>
  <time datetime="2020-09-07 10:00">September 7th, 10am</time>
  <h3>Frontend Developer Festival</h3>
  <p>Tokyo, Odaiba, Big Sight</p>
  <button oo-button="primary stadium outline">Join</button>
</div>

<div oo-event="alert">
  <time datetime="2020-09-07 10:00">September 8th, 10am</time>
  <h3>Frontend Developer Festival</h3>
  <p>Tokyo, Odaiba, Big Sight</p>
  <button oo-button="alert stadium outline">Join</button>
</div>

0 class, 1 event component + 1 button component & 3 modifers

Frontend Developer Festival

Tokyo, Odaiba, Big Sight

Frontend Developer Festival

Tokyo, Odaiba, Big Sight


Adjust Html elements << >> Use Column