ATL_DEV
ATL_DEV

Reputation: 9591

Is it possible to alias a class or tag to another class or tag in SASS or LESS?

I am trying to make my bootstrap 2.1 markup more semantic using Less or possibly Sass. Consider the following markup for Bootstrap's standard navigation bar:

<header id="main-nav" class="navbar navbar-static-top" role="banner">
    <nav class="navbar-inner" role="navigation">
        <div class="container">

            <!-- Collapse nav button -->
            <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>

            <!-- Nav -->
            <nav id="navlinks" class="nav-collapse collapse pull-right">
                <ul class="nav nav-pills">
                    <li class="active">@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                </ul>
            </nav>
        </div>
    </nav>
</header>

Obviously, it is easy to change DIVs to more semantic HTML 5 tags, but removing the chain of classes from the markup is more difficult. If you were to use mixins like:

header #main-nav {
    .navbar;
    .navbar-static-top;
}

The following definition wouldn't work because compound classes are not effected:

.navbar .btn-navbar {
    display: none;  // hide button in full width (Why a compound class? Redundant?)
}

Ideally, it would be nice if less or sass had such a syntax:

header#main-nav $= .navbar;  // copy .navbar definitions using #main-nav as the name

or

header#main-nav @= .navbar;  // rename .navbar definitions to #main-nav

Can this be done? If not, how can I achieve semantic markup?

Upvotes: 8

Views: 7366

Answers (1)

cimmanon
cimmanon

Reputation: 68319

There is no aliasing as you say it, but LESS and Sass both have the ability to write like this:

.navbar, #main-nav {
    .collapse {}
}

Which would output like this:

.navbar .collapse, #main-nav .collapse {}

Sass has a unique directive called @extend, which functions like this:

%common-styles {
    .collapse {}
}

.navbar {
    // unique navbar styles
    @extend %common-styles
}

#main-nav {
    // unique main-nav styles
    @extend %common-styles
}

The output would be identical to the output of the first for this simplified case, but allows you to add additional styling in an elegant way.

Update for rephrased question:

I use classes very sparingly, only to describe the collection of elements as a whole (is it a movie listing? Is it information about a client? Is it a call to action element?) and let descendant selectors take care of the rest. Chained classes (ala OOPCSS) are largely unnecessary when using a CSS Preprocessor: it can assemble styles for you.

In a theoretical Sass bootstrap, we might define a few things we like to reuse for navigation elements no matter what site we are designing (LESS has a slightly different syntax, but it can do this too).

@mixin drop-menu { // intended for use with ordered or unordered lists that contain unordered lists
    & > li {
        @include inline-menu;
        ul { display: none }
        &:hover {
            ul { display: list }
        }
    }
}

@mixin inline-menu { // use with ordered or unordered lists if you'd like
    display: inline;
    margin-right: 1em;
    & + li { margin-left: 1em; border-left: 1px solid }
}

@mixin subtle-box { // just a box with a subtle gradient and slightly rounded corners
    linear-gradient(white, #CCC);
    border-radius: .25em;
    padding: .5em;
}

@mixin clearfix {
    &:after {
        content: " ";
        display: table;
        clear: both;
    }
}

None of these items are part of your CSS until you ask them to be.

body > header nav { // this is our main navigation element
    @include drop-menu;
    @include subtle-box;
    color: blue;
    font-family: garamond, serif
}

nav.admin {
    @include inline-menu;
    color: orange;
}

section.gallery {
    @include clearfix;
    img { float: left; padding: 0 10px 10px 0 }
}

Now if you have multiple elements that are very different but have a good chunk of styling in common, by all means use the @extend directive mentioned in the original answer.

If you're deciding between Sass and LESS, Sass has considerably more features (like the really cool @extend directive, functions, lists, etc.). I initially chose LESS because it had a nice 3rd party Windows compiler so I didn't have to install Ruby on my virtual box, but fought against the language constantly (these variable variables are useless!).

Upvotes: 5

Related Questions