Arrows are small triangles by default set to 5px base.
#arrow > .left(@arrowWidth: 5px);
#arrow > .right(@arrowWidth: 5px);
#arrow > .above(@arrowWidth: 5px);
#arrow > .below(@arrowWidth: 5px);
Pointers are arrows with larger base, and enough margins next to them.
#pointer > .left(@arrowWidth: 6px);
#pointer > .right(@arrowWidth: 6px);
#pointer > .up(@arrowWidth: 6px);
#pointer > .down(@arrowWidth: 6px);
#pointer > .diagonalupleft(@arrowWidth: 8px);
#pointer > .diagonalupright(@arrowWidth: 8px);
#pointer > .diagonaldownleft(@arrowWidth: 8px);
#pointer > .diagonaldownright(@arrowWidth: 8px);
Arrow functions define as little as possible to generate the triangle, it is best used within containers of inline-block
or in pseudo element.
// exampel of arrow above
.arrow-above {
&:before {
display: inline-block;
margin-right: @space;
content: '';
#arrow > .above();
}
}
// example of pointer up
.pointer-up {
&:before {
display: inline-block;
content: '';
#pointer > .up();
}
}
#arrow > .left(10px);
#pointer > .right(10px);
If used with position: absolute
basic positioning occurs based on intended
context. This is pretty subjective, in order to define your own positioning, you can override the position
values, or you can position parent block as fits.
.coloredarrow {
display: flex;
justify-content: center;
align-items: center;
width: 50px;
height: 50px;
padding: @halfspace;
border:1px solid @grey-light;
border-radius: 1000px;
&:before {
border-color: @yellow;
content: '';
display: inline-block;
#arrow > .right(10px);
}
}
Set the size to rem
or px
, or multiply font by a factor, to control responsive behavior.
// pass a value equal to 1 rem, it will output either 1 rem, or 10 px,
// depending on @rem-enabled option
#rem > .font-size(@font-size);
// multiple the font passed by a factor of @resFontFactor
// depending on @enable-res-fonts option
#rem > .res-font-size(@font-size);
Usage: this helps in making fonts responsive by a predefined fraction, without fine tuning them.
// set font to 1.5 rem, if @rem-enabled is true, 15px if not
.responsivefont {
#rem > .font-size(1.5);
}
.media(md, {
.responsivefont {
// set font to 1.5rem * @resFontFactor if @rem-enabled and @enable-res-fonts are true
// or 15px * @resFontFactor if @rem-enabled is false
// or 1.5rem if @enable-res-fonts is false
// or 15px if both are false
#rem > .res-font-size(1.5);
}
});
Set the font color in contrast to the background color, using LESS contrast
function. This is a shortcut used with the following (still in beta):
// the function uses @text-color, @white, @front-color-contrast variables
color: contrast(@c, @text-color, @white, @front-color-contrast);
// usage
.fcolor (@c);
// also, set background color to @c and front color to contrast
.colorbox(@c)
Example:
.colorcontrast-light {
.box();
background-color: @yellow-light;
.fcolor($background-color);
// or for short .colorbox(@yellow-light);
}
.colorcontrast-dark {
.box();
background-color: @green;
.fcolor($background-color);
// or for short .colorbox(@green);
}
.ellipsis();
/* generates the following props
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
*/
.tight-box {
.ellipses();
}
Two functions are used a lot, the gradient to bottom, and to right. Thus making it simply, two shortcuts are created.
// to bottom, default 0 to 100%
.gradient(@start-color, @end-color, @start-location: 0%, @end-location: 100%);
// to right, default 0 to 100%
.gradient-h (@start-color, @end-color, @start-location: 0%, @end-location: 100%);
// usage:
.grdbox {
.gradient(white, black);
}
Those are quick shortcuts to define different media stops for screen and min-width
, and screen and max-width
. Note the width cut-offs must be defined in @screen
collection in the variables file.
// produces rules inside @media only screen and (min-width: @screen[md])
// where @screen[md] is defined as 720px
.media(md, {
// add rules here
.my-font {
font-size: 140%;
}
});
// produces rules inside @media only screen and (max-width: @screen[md])
.mediamax(md, {
.red-md {
span {
color: red;
}
}
});
// add your own cut-off in variables file:
@screen: {
xs: 480px; // special cases
sm: 600px; // mobile interface
md: 720px; // tablet portrait
lg: 960px; // the usual desktop and landscape tablets
xl: 1200px; // more popular small desktop
ds: 1600px; // up above desktop
mynewscreen: 1100px;
};
// then use it
.media(mynewscreen, {
// min-width 1100px rules here
});
.my-font
is larger on screens > 720px
.red-md
is red on screens < 720px
To quickly define the shape of the scrollbar for webkit browsers, and a specific width, use the shortcut: .scroll()
. This is very handy when making prototypes, and the definiton is very basic. To use it, define the overflow and height.
// defaults to 9px width
.scroll(@width: 9px);
// example:
.scrollme {
overflow-x: hidden;
overflow-y: auto;
.hm-1();
.scroll();
}
.scrollme-x {
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
.scroll(2px);
}
Use the main button template to create new buttons, or redefine the button template, change some properties, or add new properties, by accessing this function:
button
selector is normalized, but the .btntemplate
applies only to .btn-
classes.// btn-template inside the box looks like this
.btntemplate(){
padding: @button-padding-v @button-padding-h;
display: inline-block;
transition: background-color .518s;
line-height: 1;
.border-radius(@radius);
text-transform: uppercase;
font-size: 90%;
cursor: pointer;
border: 0;
}
// buttons have upper-case default definition, let's remove that
.btntemplate() {
text-transform: none;
}
// create a new button based on the same template
.btn-orange {
.btntemplate();
color: @white;
background-color: orange;
}
The grid system already has definitions to the major 12 columns, but those classes are not accessed in LESS files, because they are generated. So in order to define widths using the same grid system, for example for a more controled, declarative style of a specific reused component, use the following functions in LESS files.
// define grid in less for a contact card
.contact-card {
// make a row
.row();
> div {
// ensures 100% width
.col();
}
.name {
// 4/12 (@wrapper is set to 12 in variables)
.columns(4);
}
.other {
// 8/12
.columns(8);
}
dl {
.row();
dt {
font-size: 80%;
color: @text-light;
.columns(6);
}
dd {
.columns(6);
}
dd.signature {
// margin-left by 6/12 columns
.offset(6);
}
}
}
.media(md, {
.contact-card {
.name {
.columns(3);
}
.other {
.columns(9);
}
dl {
dt {
.columns(4);
}
dd {
.columns(8);
}
dd.signature {
.offset(4);
}
}
}
});
// the following generates width: 37.5% (4.5 / @wrapper * 100)
.myc-4-lookalike {
.columns(4.5);
}
// the following generates width: calc(37.5% - 10px);
.myc-4-lookalike-off {
.columns(4.5, 10px);
}
Also, you can auto generate definitons for columns with different labels, using the following generators. Shut defines grid layout for only three screen cut-offs: plain, min-width: md
, and min-width: lg
. Use these functions with combinations of media queries to generate more screen cut-offs.
@wrapper
as the base of the grid system. By default, it is 12.
// generates basic
.generate-column(5, bleh); // generates bleh-1, .ubleh-1 > li to .bleh-5, .ubleh-5 > li
.generate-offset(5, bleh); // generates .offset-bleh-1 to .offset-bleh-5
.generate-grid(5, gbleh); // generates .gbleh-1 to .gbleh-5, use inside display: grid
/* generates .bleh-spaced > .bleh-1, .bleh-spaced.ubleh-1 > li
to .bleh-spaced > .bleh-3,.bleh-spaced.ubleh-3 > li
using @halfspace value as the space between columns */
.bleh-spaced {
.generate-spaced-column(3, bleh);
}
.bleh-spaced
allows for some gaps between columns. The way to do that is wrap with row-spaced
which adds justify-content: space-between;
. Then every .bleh-spaced
element, has a calculated reduction in width. This allows for gaps between columns without using gap
css property (which is not yet supported on Safari), but with the disadvantage that you must fill the 12 columns, otherwise it would like this:
For grid template, the container is .grid (display: grid)
. Shut only contains the simplest grid, where the first column width is defined, and the second is auto
. This pattern is so repetaed in prototyping, it needed its own function.
The offset-
classes add margin-left
calculated values relative to the @wrapper
value, allowing gaps in grid layout of specific number of columns. Alone, they look like this:
Here is an example of generating grid layout with xl
screen cut-offs:
.media(xl, {
/* generates .offset-xl-c1 to .offset-xl-c11 */
.generate-offset(11, xl);
/* generates .xl-1 to .xl-12,
and .uxl-1 > li to .uxl-12 > li */
.generate-column(12, xl);
// generats .gxl-1 to .gxl-11 with grid template
.generate-grid(11, gxl);
/* generates .row-spaced > .xl-1 to .row-spaced > .xl-12
and .row-spaced > .uxl-1 to .row-spaced > .uxl-12
with slightly smaller percentages to accomodate for spacing */
.row-spaced {
.generate-spaced-column(12, xl);
}
});
The following functions produce heights multiplied by factor @grid-column-height
. Out of the box, Shut defines min-height and max-height with 1 multiplier to 6. Here is how to add more.
/* generate .h-7 to .h-12, .uh-7 to .uh-12 with min-height */
.generate-min-heights(7, 12);
/* generate .hm-7 to .hm-12, .uhm-7 to .uhm-12 with max-height */
.generate-max-heights(7, 12);
The symbol definition function defines all icons generated by
.getIcon()
function.
@enable-icon-font
is true.// .symbolDef inside the box looks like this:
.symbolDef() {
font-family: @icon-font;
text-transform: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
display: inline-block;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
speak: none;
font-smooth: always;
/* enable ligatures ================ */
letter-spacing: 0;
-webkit-font-feature-settings: 'liga';
-moz-font-feature-settings: 'liga=1';
-moz-font-feature-settings: 'liga';
-ms-font-feature-settings: 'liga' 1;
-o-font-feature-settings: 'liga';
font-feature-settings: 'liga';
-webkit-font-variant-ligatures: discretionary-ligatures;
font-variant-ligatures: discretionary-ligatures;
/* ligatures? */
content: attr(data-icon);
}
// let's fine tune some properties for the current project
.symbolDef() {
vertical-align: middle;
font-size: 150%;
}
// pass name of class, and the character value
.icon(@name, @value);
/* to generate:
.@{name} {
&:before {
content: @value;
}
}
*/
// adds symbol definiton to :before with "value" as content
.getIcon(@value);
// adds symbol definition to :after with "value" as content
.getIcon(@value, "after");
// adds content prop (only) to :before
.changeIcon(@value);
// adds content prop (only) to :after
.changeIcon(@value, "after");
// generates content and font-family props
.displayIcon(@value);
// save the icon in a variable to re-use
@icon-place: "\e900";
@icon-right: "\e904";
@icon-down: "\e902";
@icon-up: "\e905";
// this produces .icon-place class ready to use, no symbol association with it yet
.icon(icon-place,@icon-place);
// .getIcon to generate symbol definition and content
.my-new-icon {
.getIcon(@icon-place);
color: @red;
}
// pass "after" as a second argument to use :after instead
.next-icon {
.getIcon(@icon-right, "after");
}
// use .changeIcon(value) to overwrite content only of :before
.expand-icon {
color: @green;
.getIcon(@icon-down);
&.expanded {
.changeIcon(@icon-up);
}
}
// pass "after" as a second argument to overwrite content of :after
.collapse-icon {
color: @red;
.getIcon(@icon-up, "after");
&.collapsed {
.changeIcon(@icon-down, "after");
}
}
// and display an icon in a pseudo element
.fancy-icon {
position: relative;
text-align: center;
&:before {
margin: auto;
border-radius: 1000px;
display: flex;
justify-content: center;
align-items: center;
width: 50px;
height: 50px;
color: @white;
background-color: fade(@blue, 50);
.displayIcon(@icon-place);
}
}