Created
December 11, 2014 22:07
-
-
Save joaocunha/acb14dafbdfadf75e5dd to your computer and use it in GitHub Desktop.
Stylus Mixins used on the MDN Kuma project
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@require 'vars'; | |
@require 'prefixes'; | |
/* | |
Provides man mixins for use within the MDN theme. | |
*/ | |
/* searches expression for the provided string and replaces with provided value */ | |
replace($expr, $str, $val) { | |
$expr = clone($expr); | |
for $e, $i in $expr { | |
if ($e == $str) { | |
$expr[$i] = $val; | |
} | |
} | |
return $expr; | |
} | |
set-font-size(value) { | |
font-size: value; | |
if (value is not inherit) { | |
// make sure we're working with px otherwise remify will just spit out what we spat out before */ | |
u = unit(value); | |
if (u is 'px') { | |
font-size: remify(value); | |
} | |
} | |
} | |
remify(value) { | |
u = unit(value); | |
if (u is 'px') { | |
return unit(value/$base-font-size, 'rem') | |
} else { | |
return unit(value, u) | |
} | |
} | |
set-smaller-font-size() { | |
set-font-size($smaller-font-size); | |
} | |
set-larger-font-size() { | |
set-font-size($base-bump-font-size); | |
} | |
/* vendor prefixes */ | |
/* vendorizes a propery based on it's value in the prefixes.styl lookup table */ | |
vendorize($property, $value) { | |
$prefixes = $prefix-properties[''+$property]; | |
// might be a quoted because it has commas in it, example: transition-property | |
if($value is a 'string' or $value is a 'ident') { | |
$value = unquote($value); | |
} | |
if($prefixes == null) { | |
// warn if we're prefixing something unrecognized. | |
warn('Warning in vendorize(): ' + $property + ' not listed in prefixes.styl') | |
// provide unprefixed value as fallback | |
$property: $value; | |
} else { | |
for $prefix in $prefixes { | |
{$prefix + $property}: $value; | |
} | |
// warn if we're vendorizing something unneccisarily | |
if($prefixes == '') { | |
warn('Warning in vendorize() ' + $property + ' does not need to be vendorized anymore. ') | |
} | |
} | |
} | |
/* vendorizes a value indescriminately by adding the prefixes defined by VENDOR-PREFIXES */ | |
vendorize-value(property, value, more = '') { | |
for prefix in VENDOR-PREFIXES { | |
{property}: unquote(prefix + value + more); | |
} | |
{property}: unquote(value + more); | |
} | |
/* prevents spacing of a given element if it's the last child */ | |
prevent-last-child-spacing(element = '*', property = 'padding') { | |
if (element is '*') { | |
element = unquote(element); | |
} | |
& > {element}:last-child { | |
{property}: 0; | |
} | |
} | |
prevent-last-child-bottom-spacing(element = '*') { | |
prevent-last-child-spacing(element, margin-bottom); | |
prevent-last-child-spacing(element, padding-bottom); | |
} | |
/* text-decoration none, hover text-decoration underline */ | |
reverse-link-decoration() { | |
a { | |
text-decoration: none; | |
&:hover, &:active, &:focus { | |
text-decoration: underline; | |
} | |
} | |
} | |
/* converts an rgba value to hex, blending on white or the provided background hex/rgb (must provide flat colour for background) */ | |
rgba-to-hex($color, $bg = #fff) { | |
if(typeof($color) == 'rgba') { | |
$a = alpha($color); | |
$fallback = $color * $a + $bg * (1 - $a); | |
return $fallback; | |
} else { | |
error('rgba-to-hex() must be used passed an rgba value'); | |
} | |
} | |
/* creates a hex fallback of a property using an rgba value | |
will use white as the background matte if no colour is provided | |
example input: .test { border: 20px solid rgba-fallback(rgba(255,0,0,0.5), #000);} | |
example output: .test { border: 20px solid #800000; border: 20px solid rgba(255,0,0,0.5); } | |
*/ | |
rgba-fallback($color, $bg = #fff) { | |
// check mixin was called inside a property | |
if (current-property) { | |
// check mixin was passed an rgba | |
if(typeof($color) == 'rgba') { | |
// get value of property | |
$val = current-property[1]; | |
// create our fallback hex | |
$fallback-hex = rgba-to-hex($color, $bg); | |
// replace the rgba with the hex in the value of the property | |
$hex-val = replace($val, '__CALL__', $fallback-hex); | |
// add a duplicate property with the fallback value | |
add-property(current-property[0], $hex-val); | |
} else { | |
error('rgba-fallback() must be given an rgba value'); | |
} | |
// return the rgba for use in the original property | |
$color | |
} else { | |
error('rgba-fallback() must be used within a property'); | |
} | |
} | |
/* generates a background property for header and zones */ | |
create-gradient-background(color = '', use-gradient = false) { | |
if use-gradient { | |
background-image: url($media-url-dir + 'header-background.png'), url($media-url-dir + 'mdn-header-gradient.png'); | |
background-repeat: repeat, repeat-x; | |
} else { | |
background-image: url($media-url-dir + 'header-background.png'); | |
background-repeat: repeat; | |
} | |
background-position: 0 0, 0 0, 0 0; | |
if color { | |
background-color: color; | |
} | |
} | |
create-home-gradient-background(color) { | |
create-gradient-background(color); | |
background-image: url($media-url-dir + 'header-background.png'), url($media-url-dir + 'blueprint.png'), url($media-url-dir + 'mdn-header-gradient.png'); | |
background-repeat: repeat, repeat, repeat-x; | |
} | |
/* generates a cross-browser gradient */ | |
create-gradient(start-color, end-color, direction = false) { | |
if direction { | |
vendorize-value(background, linear-gradient, '(' + direction + ', ' + start-color + ', ' + end-color + ')'); | |
} else { | |
vendorize-value(background, linear-gradient, '(' + start-color + ', ' + end-color + ')'); | |
} | |
filter: unquote("progid:DXImageTransform.Microsoft.gradient(startColorstr='" + start-color + "', endColorstr='" + end-color + "', GradientType=1)"); /* IE6-9 */ | |
} | |
/* generates the essential "before" and "after" code for pseudo-arrows */ | |
generate-arrow(arrow-width = 10px) { | |
&:before, &:after { | |
content: ' '; | |
height: 0; | |
position: absolute; | |
width: 0; | |
border: arrow-width solid transparent; | |
} | |
} | |
/* used to create sliding animations */ | |
slider(duration=$default-animation-duration, maximum-height = 10000px) { | |
overflow-y: hidden; | |
max-height: maximum-height; | |
vendorize(transition-property, all); | |
vendorize(transition-duration, duration); | |
vendorize(transition-timing-function, $slide-timing-function); | |
&.closed { | |
max-height: 0; | |
} | |
} | |
/* sets the base styles for messages (review, warning, error, notice, etc.) */ | |
set-message-base(remove-last-spacing = true) { | |
border-width: 5px; | |
border-style: solid; | |
padding: ($grid-spacing / 2); | |
margin-bottom: $grid-spacing; | |
set-smaller-font-size(); | |
if(remove-last-spacing) { | |
& *:last-child { | |
margin-bottom: 0; | |
padding-bottom: 0; | |
} | |
} | |
} | |
/* removes the implied "<main>" spacing so page is more customizable */ | |
remove-main-spacing() { | |
main > .center { | |
width: auto; | |
padding: 0; | |
margin: 0; | |
max-width: none; | |
} | |
} | |
add-center-spacing(spacing = $gutter-width) { | |
padding-left: spacing; | |
padding-right: spacing; | |
} | |
remove-center-spacing() { | |
padding-left: 0; | |
padding-right: 0; | |
} | |
/* overrides the navigation menu color - zones and homepage */ | |
override-main-nav-color(hex) { | |
#main-nav > ul > li > a, | |
.user-state, | |
.user-state a, | |
.submenu-close { | |
color: hex; | |
} | |
#main-nav > ul > li { | |
.search-wrap { | |
background-color: rgba-fallback(rgba(255, 255, 255, 0.4)); | |
input, i, .search-trigger { | |
color: hex !important; | |
} | |
input { | |
set-placeholder-style(color, hex); | |
} | |
} | |
} | |
} | |
/* overrides the size of the navigation search box on certain pages */ | |
minimize-header-search() { | |
.main-nav-search { | |
width: 36px; | |
@media $media-query-mobile { | |
width: auto; | |
} | |
} | |
.search-wrap input { | |
width: 22px; | |
&:focus { | |
width: 500px; | |
} | |
} | |
} | |
/* sets an input tag's placeholder styles */ | |
set-placeholder-style(prop, value) { | |
&::-webkit-input-placeholder { | |
{prop}: value; | |
} | |
&::-moz-placeholder { | |
{prop}: value; | |
} | |
} | |
/* uses the white logo instead of color logo */ | |
use-white-logo() { | |
#main-header .logo { | |
background-position: 0 -41px; | |
} | |
} | |
/* for use */ | |
/* | |
Allows setting of a property for LTR and RTL without having to deal with duplicating and maintaining selectors: | |
example: bidi-style(left, 20px, right, auto) | |
*/ | |
bidi-style(ltr-prop, value, inverse-prop, inverse-value, make-important = false) { | |
make-important = make-important ? unquote('!important') : unquote(''); | |
{ltr-prop}: value make-important; | |
html[dir='rtl'] & { | |
if (ltr-prop != inverse-prop) { | |
{inverse-prop}: value make-important; | |
} | |
{ltr-prop}: inverse-value make-important; | |
} | |
} | |
bidi-value(prop, ltr, rtl, make-important = false) { | |
bidi-style(prop, ltr, prop, rtl, make-important); | |
} | |
bidi-value-vendorize(prop, ltr, rtl, make-important = false) { | |
make-important = make-important ? unquote('!important') : unquote(''); | |
vendorize(prop, ltr make-important); | |
html[dir='rtl'] & { | |
vendorize(prop, rtl make-important); | |
} | |
} | |
/* | |
MIXINS LIKE CLASSES | |
These are not dynamic but serve as mixins so that styles wont be repeated throughout files | |
*/ | |
heading-1() { | |
set-font-size(($content-block-margin * 2)); | |
letter-spacing: -2px; | |
} | |
heading-2() { | |
set-font-size(30px); | |
letter-spacing: -1px; | |
} | |
big-search() { | |
background: rgba-fallback(rgba(255, 255, 255, 0.2)); | |
set-larger-font-size(); | |
display: block; | |
margin: 0 auto; | |
border: 0; | |
border-radius: 3px; | |
font-family: $heading-font-family; | |
width: 60%; | |
} | |
offscreen() { | |
border: 0; | |
clip: rect(0 0 0 0); | |
height: 1px; | |
margin: -1px; | |
overflow: hidden; | |
padding: 0; | |
position: absolute; | |
width: 1px; | |
} | |
clearfix() { | |
clear:both; | |
&:after { | |
content: ' '; | |
clear: both; | |
display: table; | |
} | |
} | |
title-header() { | |
font-weight: bold; | |
text-transform: uppercase; | |
color: $text-color; | |
text-decoration: none; | |
display: block; | |
} | |
/* submenu generator: used in the main navigation and wiki */ | |
component-submenu(menu-width, num-columns, background-color, arrow-border-color) { | |
position: absolute; | |
padding: $grid-spacing; | |
background: background-color; | |
display: none; | |
width: menu-width; | |
box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.4); | |
component-submenu-close(); | |
.submenu-column { | |
if num-columns is 1 { | |
col-width = 100%; | |
} else { | |
col-width = ((menu-width - (num-columns * $grid-spacing) - 1) / num-columns) + ($grid-spacing / 2); | |
} | |
vertical-align: text-top; | |
width: col-width; | |
display: inline-block; | |
&:nth-child(even) { | |
bidi-style(border-left, 1px dotted #d4dde4, border-right, 0); | |
bidi-style(padding-left, $grid-spacing, padding-right, 0); | |
} | |
} | |
a { | |
set-smaller-font-size(); | |
padding: 5px 0; | |
display: block; | |
} | |
reverse-link-decoration(); | |
generate-arrow(); | |
&:before { | |
border-bottom-color: background-color; | |
position: absolute; | |
z-index: 2; | |
} | |
&:after { | |
border-bottom-color: arrow-border-color; | |
position: absolute; | |
z-index: 1; | |
} | |
@media $media-query-mobile { | |
.submenu-column, .submenu-column:nth-child(even) { | |
bidi-style(border-left, 0, border-right, 0); | |
bidi-style(padding-left, 0, padding-right, 0); | |
} | |
} | |
@media $media-query-small-mobile { | |
& { | |
width: auto; | |
.submenu-column { | |
width: auto; | |
display: block; | |
} | |
} | |
} | |
} | |
component-submenu-close() { | |
.submenu-close { | |
display: none; | |
position: absolute; | |
top: 20px; | |
bidi-style(right, 0, left, auto); | |
i { | |
margin-left: 0; | |
} | |
} | |
@media $media-query-tablet { | |
.submenu-close { | |
display: block; | |
} | |
} | |
} | |
/* When an element contains a label and a checkbox in order (as on the edit | |
profile page and elsewhere) make them appear on the same line, with the | |
checkbox to the left of the label. */ | |
$checkbox-label-container { | |
clearfix(); | |
input[type='checkbox'] { | |
bidi-value(float, left, right); | |
} | |
label { | |
position: absolute; | |
bidi-style(margin-left, 25px, margin-right, 0); | |
} | |
} | |
/* Dropdown menus that hide advanced feature, such as the "This Page" menu on | |
article pages, the "Advanced" menu on profiles, etc. */ | |
$advanced-menu { | |
component-submenu(160px, 1, $button-background, $button-shadow-color); | |
bidi-style(right, 0, left, auto); | |
top: 40px; | |
z-index: 3; | |
border-top: 1px solid $button-shadow-color; | |
width: 160px !important; /* needs this due to overriding media query rule of component */ | |
bdi { | |
bidi-value(text-align, left, right); | |
} | |
&:before { | |
bidi-style(right, 10px, left, auto); | |
top: -18px; | |
} | |
&:after { | |
bidi-style(right, 10px, left, auto); | |
top: -20px; | |
} | |
} | |
$right-icons { | |
margin-left: 0 !important; | |
margin-right: 10px !important; | |
} | |
/* Styles for code blocks - used for wiki document and WYSIWYG editor */ | |
$code-block { | |
background: $code-block-background-color; | |
border-left: 6px solid $code-block-border-color; | |
background-image: url($media-url-dir + 'blueprint-dark.png'); | |
background-position: top center; | |
background-repeat: repeat; | |
vendorize(tab-size, 4); | |
vendorize(hyphens, none); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment