Skip to content
On this page

Introduction

Oruga is a lightweight library of UI components for Vue.js without CSS framework dependency.
It doesn't depend on any specific style or CSS framework (like Bootstrap, Bulma, TailwindCSS, etc) and it doesn't provide any grid system or CSS utility, it just offer a set of components easy to customize only modifying your stylesheets or integrating it with a CSS framework (see the demo).
Oruga wants you to focus only on UI/UX aspects of your application and be totally flexible to future changes without having to touch a line of JavaScript.

If you need a component library and want to easily apply your custom styles, Oruga is the library for you! ๐Ÿ›

Oruga default stylesheet

Oruga comes with a default stylesheet containing only the essential rules for Oruga components such as display, position, z-index and other basic attributes. You can use the default Oruga stylesheet in this documentation turning on the switch in the navbar.

If you use the default stylesheet to browse documentation some examples won't work as you expect because sizes, variants and adornments are not included in the Oruga default stylesheet. For more info read "Differences between default and full css" or go to "Customization section" if you want to know more about components customization.

Availability

๐Ÿ› Oruga is available for Vue.js version 3.x and has been tested in all major browsers

ChromeFirefoxOperaSafariEdge
Latest โœ”Latest โœ”Latest โœ”Latest โœ”Latest โœ”

๐Ÿ’… For more info about components customization, go to the "Customization section".

๐Ÿ•น To see Oruga in action, go to the "Examples" section.

Setup

bash
yarn add @oruga-ui/oruga-next
bash
npm install @oruga-ui/oruga-next --save
html
<link rel="stylesheet" href="https://unpkg.com/@oruga-ui/oruga-next/dist/oruga.min.css" />
<script src="https://unpkg.com/@oruga-ui/oruga-next/dist/oruga.min.js"></script>

Full bundle

js
import { createApp } from 'vue'
import Oruga from '@oruga-ui/oruga-next'
import '@oruga-ui/oruga-next/dist/oruga.css'

createApp(...).use(Oruga);

Individual components (tree shaking)

js
import { createApp } from 'vue'
import { OAutocomplete, OSidebar } from '@oruga-ui/oruga-next'
import '@oruga-ui/oruga-next/dist/oruga.css'

createApp(...)
  .component(OAutocomplete)
  .component(OSidebar)

Nuxt module

Oruga doesn't provide a Nuxt.js module at the moment.

You can use Nuxt.js plugins system adding a file (e.g. oruga.js) in your plugins folder containing

js
import Oruga from '@oruga-ui/oruga-next'
import '@oruga-ui/oruga-next/dist/oruga.css'

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(Oruga)
})

To make this plugin available in your app, add this file to the plugins array in your nuxt.config.js

js
plugins: [{ src: '~plugins/oruga.js' }]

To understand how the plugins work with Nuxt.js, take a look at the NuxtJS plugin documentation.

Customization

Oruga allows you to customize components in 3 different ways:

You can mix them, for example adding new classes and using CSS variables!

Oruga provides oruga.css, a lightweight stylesheet containing only minimal CSS rules (position, display, z-index ...). Include it if you want to perform a complete customization.

Oruga provides other 2 different stylesheets:

  • oruga-full.css: a stylesheet containing the complete Oruga style (the default style used for documentation).
  • oruga-full-vars.css: a stylesheet containing the complete Oruga style with css vars you can redefine in your application. For more information click here.

For more info read "Differences between default and full css".

Adding new classes or override existing ones

With Oruga you can easily override existing components style appending one or more classes. Each component has a Class prop section (for example see Dropdown Class props) where you can inspect elements each class property affects using the Class prop inspector.

Adding classes

You can add classes to a component using class properties (see Autocomplete class props for example)

vue
<o-autocomplete root-class="myautocomplete-root" menu-class="myautocomplete-menu" item-class="myautocomplete-item" />

Or globally

js
import { createApp } from 'vue'
import Oruga from '@oruga-ui/oruga-next'
import '@oruga-ui/oruga-next/dist/oruga.css'

createApp(...)
    .use(Oruga, {
        autocomplete: {
            rootClass: 'myautocomplete-root',
            menuClass: 'myautocomplete-menu',
            itemClass: 'myautocomplete-item',
            ...
        }
    });

If you use individual imports you can customize each compoment using Config plugin.

js
import { createApp } from 'vue'
import { OAutocomplete, OSidebar, Config } from '@oruga-ui/oruga-next';

createApp(...)
    .component(OAutocomplete)
    .component(OSidebar)
    .use(Config, {
        autocomplete: {
            rootClass: 'myautocomplete-root',
            menuClass: 'myautocomplete-menu',
            itemClass: 'myautocomplete-item',
            ...
        }
    });

You can also use an array to specify more than one class or a function to extend or override classes in a component. In case you use a function, a suffix is provided by the component and it can be used inside the function. For example, menuPositionClass in Autocomplete provides a suffix to specify menu position (top, bottom), in this case you may define a function and append the suffix to the base class name

js
createApp(...)
    .use(Config, {
        autocomplete: {
            rootClass: 'myautocomplete-root',
            menuClass: 'myautocomplete-menu',
            menuPositionClass: {
                class: (suffix) => {
                    return `myautocomplete-menu-${suffix}`
                }
            },
            itemClass: 'myautocomplete-item',
        }
    })

For a better customization experience this function accepts the component's context containing its read-only attributes (props, data and computed) as second parameter. For example using Bootstrap you may want to apply variants to buttons only when the element is not outlined

js
createApp(...)
    .use(Config, {
        input: {
            rootClass: (_, context) => {
                if (context.computed.hasIconRight) {
                    return 'has-icons-right')
                }
            },
            variantClass: (variant, context) => {
                if (!context.props.outlined) {
                    return `btn-${variant}`
                }
            }
        },
        ...
    }

Deal with specificity

Oruga CSS comes with the lowest specifity possible, that's why you can easily override existing classes by defining new ones in the global configuration or using attributes. However there are some cases where specificty is higher than you expect, for example in the Steps component the nav item contains a marker and a divider which colors change whether the nav item is active or not.

scss
.o-steps {
    ...
    &__nav-item-active {
        .o-steps__link {
            cursor: default;
        }

        .o-steps__marker {
            @include avariable('background-color', 'steps-maker-default-color', $steps-maker-default-color);
            @include avariable('border-color', 'steps-active-color', $steps-active-color);
            @include avariable('color', 'steps-active-color', $steps-active-color);
        }

        .o-steps__divider {
            background-position: left bottom;
        }
    }

    &__nav-item-previous {
        .o-steps__marker {
            @include avariable('color', 'steps-maker-default-color', $steps-maker-default-color);
            @include avariable('background-color', 'steps-previous-color', $steps-previous-color);
        }

        .o-steps__divider {
            background-position: left bottom;
        }
    }
    ...
}

If you want to change the color you can use !important or change variables values. Otherwise you can easily increase the specificity in your stylesheet

css
.steps-nav-item-active .step-marker {
  color: blue;
  border-color: blue;
}

.steps-nav-item-active .step-divider {
  background-color: blue;
}

.steps-nav-item-previous .step-marker {
  background-color: blue;
}

.steps-nav-item-previous .step-divider {
  background-color: blue;
}

and then configure Oruga to use your custom classes

js
createApp(...)
    .use(Oruga, {
        steps: {
            itemActiveClass: 'steps-nav-item-active',
            itemPreviousClass: 'steps-nav-item-previous',
            stepMarkerClass: 'step-marker',
            stepDividerClass: 'step-divider',
        }
    });

You can see this code in action in Oruga multiframework example(code here)

Sometimes components change how elements are positioned (horizontally, vertically...), this is another case of higher specificity. In the Steps component the vertical attribute disposes the steps vertically changing the height of the steps divider.

scss
.o-steps {
    &__wrapper-vertical {
        display: flex;
        flex-direction: row;

        .o-steps__divider {
            height: 100%;
            @include avariable('width', 'steps-divider-height', $steps-divider-height);
            top: -50%;
            left: calc(50% - #{$steps-divider-height / 2});
        }

        ...
    }
    ...
}

If you want to set height to 50% keeping the other attributes unchanged you can't just define a new class (unless you want to use !important), because of a higher specificity. In that case, we suggest to define your new class in this way

css
.steps-vertical .step-divider {
  height: 50%;
}

and in your configuration

js
createApp(...)
    .use(Oruga, {
        steps: {
            verticalClass: 'steps-vertical',
            stepDividerClass: 'step-divider'
        }
    });

In Oruga documentation you'll find a special note (๐Ÿ”) in the Class prop inspector for classes with a higher specificity.

Overriding classes

In case you want to override Oruga existing classes completely, you can act as above and set the field override to true.

js
import { createApp } from 'vue'
import Oruga from '@oruga-ui/oruga-next'
import '@oruga-ui/oruga-next/dist/oruga.css'

createApp(...)
    .use(Oruga, {
        autocomplete: {
            override: true,
            rootClass: 'myautocomplete-root',
            menuClass: 'myautocomplete-menu',
            itemClass: 'myautocomplete-item',
            ...
        }
    });

or directly in your component

html
<o-autocomplete
    override
    rootClass="myautocomplete-root">

WARNING

In this case override property replaces Oruga existing classes completely, ignoring your configuration.

You can also specify the override behaviour for each class

js
createApp(...)
    .use(Config, {
        autocomplete: {
            rootClass: {
                class: 'myautocomplete-root',
                override: true
            },
            menuClass: 'myautocomplete-menu',
            itemClass: 'myautocomplete-item',
            ...
        }
    });

Transform classes

In case you want to transform applied classes' names you can use transformClasses function directly in your configuration.

js
createApp(...)
    .use(Config, {
        button: {
            transformClasses: (appliedClasses) => {
                return appliedClasses.replace(/-/g, '--')
            }
        }
        ...
    })

You can also use transformClasses globally if you need to transform classes for any component.

js
createApp(...)
    .use(Config, {
        transformClasses: (appliedClasses) => {
            return appliedClasses.replace(/-/g, '--')
        }
        ...
    })

Using CSS or SASS/SCSS variables

You can easily customize Oruga using CSS or SASS/SCSS variables. Each component has its own variables, mostly of them with default values defined in the base style (see utilities/_variables.scss).

To use CSS variables you have to import oruga-full-vars.css stylesheet

js
import '@oruga-ui/oruga-next/dist/oruga-full-vars.css'

and redefine the variables you want to change.

For example to change variants globally using CSS variables you can do

css
:root {
  --oruga-variant-primary: green;
  --oruga-variant-danger: red;
}

or a specific component variable, such as button icon width

css
:root {
  --oruga-button-icon-width: 2.5em;
}

To use SASS/SCSS variables you have to use .scss files placed in the Oruga package

js
import '@oruga-ui/oruga-next/src/scss/oruga-full-vars';

WARNING

In order to work with SASS/SCSS you might also have to install sass and sass-loader depending on your environment.

An example can be found in the Button style section: here you'll find the complete list of all the CSS and SASS/SCSS variables (with their respective default values) you can redefine for each component.

Configuration

Oruga allows to customize each components using config constructor or programmatically using this.$oruga.config.

js
{
    globalfield: string|boolean|number|function|....,
    componentname: {
        override: boolean,
        customfieldX: string|boolean|number|function|....
    }
}

For example:

js
{
    button: {
        override: true,
        rootClass: 'btn',
        roundedClass: 'btn-rounded',
        ...
    }
}

Differences between default and full css

The default stylesheet contains only the essantial rules for Oruga components such as display, position, z-index and other basic attributes.

For example to style a dropdown using override mode with oruga default stylesheet using TailwindCSS

js
import '@oruga-ui/oruga-next/dist/oruga.css'
css
.dropdown {
    @apply inline-flex relative;
}
.dropdown-menu {
    top: 100%;
    min-width: 12em;
    @apply absolute bg-white left-0 m-0 px-2 shadow-lg rounded-sm z-10;
}
.dropdown-item {
    @apply relative block no-underline px-1 py-2 cursor-pointer;
}

And here's how to style a dropdown using oruga-full stylesheet

js
import '@oruga-ui/oruga-next/dist/oruga-full.css'
css
.dropdown-menu {
    min-width: 12em;
    @apply bg-white m-0 px-2 shadow-lg rounded-sm z-10;
}
.dropdown-item {
    @apply no-underline px-1 py-2 cursor-pointer;
}

Take a look at the official TailwindCSS + Oruga example.

Global Props

FieldDescriptionDefault
statusIconShow status icon using field and variant proptrue
statusVariantIconDefault mapping of variant and icon name{
ย ย 'success': 'check',
ย ย 'danger': 'alert-circle',
ย ย 'info':'information',
ย ย 'warning': 'alert'
}
useHtml5ValidationDefault form components use-html5-validation attributetrue
iconPackIcon pack used internally and on the Icon component attribute'mdi'
reportInvalidInputCallback function that allows for custom behavior when HTML constraint validation would visually report that a field is invalid. Takes the input and its parent field (if any) as arguments.null

Take a look at each component docs to know all customizable fields/props by config.

Base Style

SASS VariableDefault
$base-border-radius4px
$base-font-size1rem
$base-rounded-border-radius9999px
$base-line-height1.5
$base-disabled-opacity0.5
$speed300ms
$speed-slow150ms
$speed-slower250ms
$easingease-out
$control-border-width1px
$control-height2.25em
$white#ffffff
$black#000000
$grey#7a7a7a
$grey-light#b5b5b5
$grey-lighter#dbdbdb
$primary#445e00
$primary-invert$white
$danger#b60000
$danger-invert$white
$warning#f4c300
$warning-invert$black
$success#006724
$success-invert$white
$info#005C98
$info-invert$white
$whitelist()
$sass-varstrue
$css-varstrue
$variable-prefix'--oruga-'
$sizes(
ย ย "small": .75rem,
ย ย "medium": 1.25rem,
ย ย "large": 1.5rem
)
$colors(
ย ย "primary": ($primary, $primary-invert),
ย ย "danger": ($danger, $danger-invert),
ย ย "warning": ($warning, $warning-invert),
ย ย "success": ($success, $success-invert),
ย ย "info": ($info, $info-invert)
)

Themes

Examples

TailwindCSS, Bootstrap 5, Bulma and Material demo ๐Ÿงถ

TailwindCSS 2 Recipe Demo ๐Ÿ๐Ÿ”๐ŸŸ

This simple demo shows a simple recipe website. Oruga components like Input, Radio, Loading, Switch, Collapse etc are customized using TailwindCSS 2!

Articles

Released under the MIT License.