DEV Community

Daniel Yuschick
Daniel Yuschick

Posted on • Updated on • Originally published at danyuschick.com

Rhubarb CSS - Mixins for Writing Logical CSS

Rhubarb CSS jam jar logo

At the end of 2020, I wrote about how CSS Logical Properties Are the Future of the Web & I18N. Since then, I've used and advocated for the new properties heavily as I see them as the next huge step toward creating truly fluid and inclusive UIs.

However, browser support requirements for the products I was working on didn't always align with browser support for logical properties. So I started writing and re-using various mixins to allow the gradual use of logical CSS through progressive enhancement with physical box model fallbacks when needed.

I'd first written the mixins for Styled Components. Later, I needed to convert those same mixins into a SCSS project. And it was here that Rhubarb CSS was born.

Rhubarb CSS

🚀 View Rhubarb CSS on GitHub

Rhubarb CSS is a collection of mixins to support writing progressively-enhanced logical CSS in many different flavors.

What started as a collection of mixins for just Styled Components, is now a collection of mixins for SCSS, Stylus and Less.

Rhubarb Styled Components

So what exactly do these mixins do?

import { Margin, Padding } from "@rhubarb-css/styled-components";

const Container = styled.section`
  ${Margin({ inline: "auto" })};
  ${Padding({ block: "var(--custom-property-value)" })};
`;
Enter fullscreen mode Exit fullscreen mode

This example, would generate the following CSS.

section {
  margin-inline-end: auto;
  margin-inline-block: auto;
  padding-block-end: var(--custom-property-value);
  padding-block-start: var(--custom-property-value);

  @supports not (margin-inline-end: 1rem) {
    margin-left: auto;
    margin-right: auto;
  }

  @supports not (padding-block-end: 1rem) {
    padding-bottom: var(--custom-property-value);
    padding-top: var(--custom-property-value);
  }
}
Enter fullscreen mode Exit fullscreen mode

An added benefit when using Rhubarb Styled Components is the TypeScript autocompletion of properties and values.

With the compiled CSS, the logical properties are prioritized. In environments where they're not supported, the @supports query will be triggered, and the physical-property equivalents are used as fallbacks. Eventually, as browser support catches up and becomes broad enough, the @supports query will no longer be needed.

Rhubarb CSS Scope

There were a couple key goals when creating the Rhubarb CSS library:

  1. Keep APIs consistent across projects
  2. Support all logical properties with direct physical fallbacks

Mixin APIs

Because of the support for Styled Components, the API conventions were generally pegged to this environment, as the outlier.

All property keys follow a camelCase naming convention, with any processor-specific leading character, such as $ for SCSS and @ for Less.

// Styled Components
blockSize

// SCSS
$blockSize

// Less
@blockSize

// Stylus
blockSize
Enter fullscreen mode Exit fullscreen mode

Logical Property Support (v0.2.0)

Here is a list of logical property support and their fallback properties.

Border

Prop CSS Property (Fallback)
border border
borderColor border-color
borderStyle border-style
borderWidth border-width
block border-block-start/end (border-top/bottom)
blockColor border-block-start/end-color (border-top/bottom-color)
blockStyle border-block-start/end-style (border-top/bottom-style)
blockWidth border-block-start/end-width (border-top/bottom-width)
blockEnd border-block-end (border-bottom)
blockEndColor border-block-end-color (border-bottom-color)
blockEndStyle border-block-end-style (border-bottom-style)
blockEndWidth border-block-end-width (border-bottom-width)
blockStart border-block-start (border-top)
blockStartColor border-block-start-color (border-top-color)
blockStartStyle border-block-start-style (border-top-style)
blockStartWidth border-block-start-width (border-top-width)
inline border-inline-start/end (border-left/right)
inlineColor border-inline-start/end-color (border-left/right-color)
inlineStyle border-inline-start/end-style (border-left/right-style)
inlineWidth border-inline-start/end-width (border-left/right-width)
inlineEnd border-inline-end (border-right)
inlineEndColor border-inline-end-color (border-right-color)
inlineEndStyle border-inline-end-style (border-right-style)
inlineEndWidth border-inline-end-width (border-right-width)
inlineStart border-inline-start (border-left)
inlineStartColor border-inline-start-color (border-left-color)
inlineStartStyle border-inline-start-style (border-left-style)
inlineStartWidth border-inline-start-width (border-left-width)

Border Radius

Prop CSS Property (Fallback)
bottomLeft border-end-start-radius (border-bottom-left-radius)
bottomRight border-end-end-radius (border-bottom-right-radius)
radius border-radius
topLeft border-start-start-radius (border-top-left-radius)
topRight border-start-end-radius (border-top-right-radius)

Layout

Prop CSS Property (Fallback)
blockSize block-size (height)
maxBlockSize max-block-size (max-height)
minBlockSize min-block-size (min-height)
inlineSize inline-size (width)
maxInlineSize max-inline-size (max-width)
minInlineSize min-inline-size (min-width)
overflow overflow
overflowBlock overflow-block (overflow-x)
overflowInline overflow-inline (overflow-y)
overscrollBehavior overscroll-behavior
overscrollBehaviorBlock overscroll-behavior-block (overscroll-behavior-x)
overscrollBehaviorInline overscroll-behavior-inline (overscroll-behavior-y)
resize resize
textAlign text-align

Margin

Prop CSS Property (Fallback)
block margin-block-start/end (margin-bottom/top)
blockEnd margin-block-end (margin-bottom)
blockStart margin-block-start (margin-top)
inline margin-inline-start/end (margin-left/right)
inlineEnd margin-inline-end (margin-right)
inlineStart margin-inline-start (margin-left)
margin margin
scroll scroll-margin
scrollBlock scroll-margin-block-start/end (scroll-margin-top/bottom)
scrollBlockEnd scroll-margin-block-end (scroll-margin-bottom)
scrollBlockStart scroll-margin-block-start (scroll-margin-top)
scrollInline scroll-margin-inline-start/end (scroll-margin-left/right)
scrollInlineEnd scroll-margin-inline-end (scroll-margin-right)
scrollInlineStart scroll-margin-inline-start (scroll-margin-left)

Padding

Prop CSS Property (Fallback)
block padding-block-start/end (_padding-top/bottom)
blockEnd padding-block-end (padding-bottom)
blockStart padding-block-start (padding-top)
inline padding-inline-start/end (padding-left/right)
inlineEnd padding-inline-end (padding-right)
inlineStart padding-inline-start (padding-left)
padding padding
scroll scroll-padding
scrollBlock scroll-padding-block-start/end (scroll-padding-top/bottom)
scrollBlockEnd scroll-padding-block-end (scroll-padding-bottom)
scrollBlockStart scroll-padding-block-start (scroll-padding-top)
scrollInline scroll-padding-inline-start/end (scroll-padding-left/right)
scrollInlineEnd scroll-padding-inline-end (scroll-padding-right)
scrollInlineStart scroll-padding-inline-start (scroll-padding-left)

Position

Prop CSS Property (Fallback)
blockEnd inset-block-end (bottom)
blockStart inset-block-start (top)
inlineEnd inset-inline-end (right)
inlineStart inset-inline-start (left)
position position
z z-index

Wrap Up

Is there a need for this? At least for me there was. So why not? Isn't that the whole point of open source? Hopefully, someone else will find it useful in moving their project toward logical properties.

Either way, I'm quite happy with this.

Resources

Discussion (0)