Reputation: 10283
I'm new to Sass and since I'm not a programmer, wrapping my head around some of the concepts is a bit hard for me, so that's why I'm asking for help.
This should be an easy one for you Sass gurus.
I need to make a mixin that I can use in different media queries. This mixin is for the main nav of the site.
The scss
looks like this:
/*Nav bar*/
a.menu-link { display:none; }
.js nav[role=navigation] { max-height:0; }
nav[role=navigation] ul { margin:0 0 0 -0.25em; border:none;
& li { display:inline-block; margin:0 0.25em;
& a { border:none; }
}
}
I'm envisioning using the mixin like this: @include navBar
, but I don't know if I'm oversimplifying it or what.
Any help is greatly appreciated.
Thanks.
Upvotes: 1
Views: 772
Reputation: 68319
For your code block, this would be one way of writing that as a mixin:
@mixin navBar {
a.menu-link { display:none; }
.js & { max-height: 0; }
ul { // note that the & isn't necessary here...
margin: 0 0 0 -0.25em;
border: none;
li {
display: inline-block;
margin: 0 0.25em;
a { border: none; }
}
}
}
nav[role=navigation] {
@include navBar;
}
If you want to customize the appearance of your nav bar, you'll have to write duplicate selectors (maybe you want to have borders on your li
s or have a special bg color on hover). It could be worse, but you wouldn't write your CSS by hand that way.
With the inclusion of nav[role=navigation]
in your selector, that block of code looks a little too specific to me, since I might want a list of stuff to display inline but it isn't part of a nav element (maybe it's a tag cloud or a list of categories).
This is a mixin from my own library that only contains the barest essentials to turn a list into an inline list (of course, it doesn't have to be a list either, it could be a container with a bunch of div
s in it if I wanted):
@mixin inline-menu($type: inline, $child: li) {
@if $type == float {
overflow: hidden;
}
> #{$child} {
@if $type == float {
float: left;
//list-style: none;
} @else {
display: inline-block;
}
@content;
a { white-space: nowrap }
}
}
I would invoke it like this:
ul.drop-menu {
margin: 0;
padding: 0;
a {
color: red;
}
@include inline-menu {
border: 1px solid red;
> a {
padding: .5em 1em;
display: block;
}
&:hover > a {
background: red;
color: orange;
}
@include drop-menu {
border: 1px solid;
padding: 1em 1em 1em 2em;
background: orange;
color: red;
margin: 0;
left: -1px;
z-index: 1;
}
}
}
Now, the advantage of doing it this way is that you don't end up with many (if any) duplicate selectors. If you want to add a border to your ul
, it is completely exposed to you because the ul
selector isn't part of the mixin at all: it is expected that the mixin is called from within some sort of container selector.
Here's the CSS that code generates:
ul.drop-menu {
margin: 0;
padding: 0;
}
ul.drop-menu a {
color: red;
}
ul.drop-menu > li {
display: inline-block;
border: 1px solid red;
position: relative;
}
ul.drop-menu > li > a {
padding: .5em 1em;
display: block;
}
ul.drop-menu > li:hover > a {
background: red;
color: orange;
}
ul.drop-menu > li ul {
display: none;
}
ul.drop-menu > li:hover ul, ul.drop-menu > li.active ul {
display: block;
position: absolute;
border: 1px solid;
padding: 1em 1em 1em 2em;
background: orange;
color: red;
margin: 0;
left: -1px;
z-index: 1;
}
ul.drop-menu > li a {
white-space: nowrap;
}
No duplicate selectors in sight. The magic behind this mixin is the @content
directive. Everything between the curly braces ({}
) is contained within @content
, which just needs to be invoked where appropriate.
Upvotes: 3