Skip to content

Instantly share code, notes, and snippets.

@stamat
Created July 6, 2018 12:27
Show Gist options
  • Save stamat/3a065ca9a94a29fdcb930f51e62e4db5 to your computer and use it in GitHub Desktop.
Save stamat/3a065ca9a94a29fdcb930f51e62e4db5 to your computer and use it in GitHub Desktop.
Neat 3.0.0 in one SASS file for Shopify theme dev
@charset "UTF-8";
// Neat 3.0.0
// http://neat.bourbon.io
// Copyright 2012 thoughtbot, inc.
// MIT License
/// This variable is a sass map that overrides Neat's default grid settings.
/// Use this to define your project's grid properties including gutters and
/// total column count.
///
/// @type map
///
/// @group settings
///
/// @name Neat grid
///
/// @property {number (unitless)} columns [12]
/// Default number of the total grid columns.
///
/// @property {number (with unit)} gutter [20px]
/// Default grid gutter width between columns.
///
/// @example scss
/// $neat-grid: (
/// columns: 12,
/// gutter: 20px,
/// );
$neat-grid: () !default;
/// If you need multiple grids in a single project, you can do
/// this by defining a new map stored within a variable of your choosing. This
/// variable can then be passed directly in to any of Neat's mixins like
/// [`grid-column(12, $my-custom-grid)`](#grid-column).
///
/// Custom grids are especially useful with [`grid-media`](#grid-media). By
/// defining a `media` attribute within your custom grid, you are able to easily
/// define gutter width and total column count as well the breakpoint at which
/// they should activate.
///
/// @type map
///
/// @group settings
///
/// @name Custom grids
///
/// @property {number (unitless)} columns [12]
/// Number of the total grid columns.
///
/// @property {number (with unit)} gutter [20px]
/// Grid gutter width between columns.
///
/// @property {number (with unit) | string | null} media [null]
/// The `@media` definition that is used by the [`grid-media`](#grid-media)
/// mixin to determine the media properties.
///
/// @property {color} color [null]
/// The color used by [`grid-visual`](#grid-visual) to create the guides.
///
/// @property {string} direction [ltr]
/// The float direction used throughout the grid.
///
/// @example scss
/// $my-custom-grid: (
/// columns: 12,
/// gutter: 20px,
/// media: 1200px,
/// color: rgba(#00d4ff, 0.25),
/// direction: ltr,
/// );
///
/// $other-custom-grid-for-print: (
/// columns: 14,
/// gutter: 1.5rem,
/// media: print,
/// );
///
$neat-custom-grid: () !default;
/// This function recives a grid map and merges it with Neat's defauls.
/// It then returns the value of the property that has been passed to it.
///
/// @argument {map} $grid
///
/// @argument {string} $setting
///
/// @return {boolean | color | list | number | string}
///
/// @example scss
/// _retrieve-neat-setting($neat-grid, columns)
///
/// @access private
@function _retrieve-neat-setting($grid, $setting) {
$_grid-settings: map-merge(_neat-merge-defaults($neat-grid), $grid);
@return map-get($_grid-settings, $setting);
}
/// Determine if a column count has been given.
/// If no columns have been given return the grid's total column count.
///
/// @argument {map} $grid
///
/// @argument {number (unitless) | null} $columns
///
/// @return {number}
///
/// @example scss
/// _neat-column-default($neat-grid, 4)
///
/// @access private
@function _neat-column-default($grid, $columns) {
@if $columns == null {
$_grid-columns: _retrieve-neat-setting($grid, columns);
@return $_grid-columns;
} @else {
@return $columns;
}
}
/// Return a calulated column width that can then be passed in to a `calc()`.
///
/// @argument {map} $grid
///
/// @argument {number} $columns
///
/// @return {string}
///
/// @example scss
/// _neat-column-width($neat-grid, 4)
///
/// @access private
@function _neat-column-width($grid, $columns) {
$_column-ratio: _neat-column-ratio($grid, $columns);
$_gutter: _retrieve-neat-setting($grid, gutter);
@if $_gutter == 0 {
@return unquote("#{percentage($_column-ratio)}");
} @else {
$_gutter-affordance: $_gutter + ($_gutter * $_column-ratio);
@return unquote("#{percentage($_column-ratio)} - #{$_gutter-affordance}");
}
}
/// Determine the ratio of `$columns` to the total column count.
/// If `$columns` is more than one value, they are handed to
/// `_neat-parse-columns()` which will determine the total columns and use this
/// value instead of `total-columns`.
///
/// @argument {map} $grid
///
/// @argument {number | list} $columns
///
/// @return {number}
///
/// @example scss
/// _neat-column-ratio($grid, 3)
///
/// @access private
@function _neat-column-ratio($grid, $columns) {
@if length($columns) > 1 {
@return nth($columns, 1) / _neat-parse-columns($columns);
} @else if $columns {
@return $columns / _retrieve-neat-setting($grid, columns);
}
}
/// Return the float direction of the grid.
///
/// @argument {map} $grid
///
/// @return {string}
///
/// @example scss
/// _neat-float-direction($neat-grid)
///
/// @access private
@function _neat-float-direction($grid) {
$_direction: _retrieve-neat-setting($grid, direction);
$_float-direction: null;
@if $_direction == "ltr" {
$_float-direction: left;
} @else if $_direction == "rtl" {
$_float-direction: right;
}
@return $_float-direction;
}
/// Apply Neat's default properties to undefined values within a map.
///
/// @argument {map} $grid
///
/// @return {map}
///
/// @example scss
/// _retrieve-neat-setting($neat-grid)
///
/// @access private
@function _neat-merge-defaults($grid) {
$_merged-grid: map-merge((
columns: 12,
gutter: 20px,
media: null,
color: rgba(#00d4ff, 0.25),
direction: ltr,
), $grid);
@return $_merged-grid;
}
/// Return the oppoite of the float direction of the grid.
///
/// @argument {map} $grid
///
/// @return {string}
///
/// @example scss
/// _neat-opposite-direction($neat-grid)
///
/// @access private
@function _neat-opposite-direction($grid) {
$_direction: _retrieve-neat-setting($grid, direction);
$_float-direction: null;
@if $_direction == "ltr" {
$_float-direction: right;
} @else if $_direction == "rtl" {
$_float-direction: left;
}
@return $_float-direction;
}
/// Parse a column count like `3 of 5` and retur the total coloumn count.
/// This is to allow a shorthand for custom grids without using a settings map.
///
///
/// @argument {list} $span
///
/// @return {number}
///
/// @example scss
/// _neat-parse-columns(3 of 5)
///
/// @access private
@function _neat-parse-columns($span) {
@if length($span) == 3 {
$_total-columns: nth($span, 3);
@return $_total-columns;
} @else if length($span) == 2 or if length($span) >= 3 {
@error "`$column` should contain 2 values, seperated by an `of`";
}
}
/// Parse media types. If the property is a string then return it, otherwise
/// assume screen and min-width.
///
/// @argument {string | number (with unit)} $media
///
/// @return {number}
///
/// @example scss
/// _neat-parse-media($grid, 1000px)
///
/// @access private
@function _neat-parse-media($media) {
@if type-of($media) == number {
@return "only screen and (min-width: #{$media})";
} @else if type-of($media) == string {
@return "#{$media}";
}
}
/// Append attributes to a the `$_grid-visual` variable in `grid-visual` mixin
///
/// @argument {map} $grid
///
/// @argument {number (unitless) | null} $columns
///
/// @return {number}
///
/// @example scss
/// _neat-column-default($neat-grid, 4)
///
/// @access private
@function _neat-append-grid-visual($grid-visual-list, $attributes) {
@each $attribute in $attributes {
$grid-visual-list: append($grid-visual-list, $attribute, comma);
}
@return $grid-visual-list;
}
/// Creates collapsed grid object that consumes the gutters of its container,
/// for use in nested layouts.
///
/// @group features
///
/// @name Grid collapse
///
/// @argument {map} $grid [$neat-grid]
/// The grid to be used to generate the collapsed container.
/// By default, the global `$neat-grid` will be used.
///
/// @example scss
/// .element {
/// @include grid-collapse;
/// }
///
/// @example css
/// .element {
/// margin-left: -20px;
/// margin-right: -20px;
/// width: calc(100% + 40px);
/// }
@mixin grid-collapse($grid: $neat-grid) {
$_grid-gutter: _retrieve-neat-setting($grid, gutter);
@if unit($_grid-gutter) == "%" {
@warn "`grid-collapse` is not compatible with percentage based gutters.";
}
margin-#{_neat-float-direction($grid)}: -($_grid-gutter);
margin-#{_neat-opposite-direction($grid)}: -($_grid-gutter);
width: calc(100% + #{($_grid-gutter * 2)});
}
/// Creates a grid column of requested size.
///
/// @group features
///
/// @name Grid column
///
/// @argument {number (unitless)} $columns [null]
/// Specifies the number of columns an element should span based on the total
/// columns of the grid.
///
/// This can also be defined in a shorthand syntaxt which also contains the
/// total column count such as `3 of 5`.
///
/// @argument {map} $grid [$neat-grid]
/// The grid to be used to generate the column.
/// By default, the global `$neat-grid` will be used.
///
/// @example scss
/// .element {
/// @include grid-column(3);
/// }
///
/// @example css
/// .element {
/// width: calc(25% - 25px);
/// float: left;
/// margin-left: 20px;
/// }
@mixin grid-column($columns: null, $grid: $neat-grid) {
$columns: _neat-column-default($grid, $columns);
$_grid-columns: _retrieve-neat-setting($grid, columns);
$_grid-gutter: _retrieve-neat-setting($grid, gutter);
width: calc(#{_neat-column-width($grid, $columns)});
float: _neat-float-direction($grid);
margin-#{_neat-float-direction($grid)}: $_grid-gutter;
}
/// Creates a grid container with clearfix.
///
/// @group features
///
/// @name Grid container
///
/// @example scss
/// .element {
/// @include grid-container;
/// }
///
/// @example css
/// .element::after {
/// clear: both;
/// content: "";
/// display: block;
/// }
@mixin grid-container($grid: $neat-grid) {
@if $grid != $neat-grid {
@warn "`grid-container` does not use grid properties. " +
"Custom grids do not need to be passed in to this mixin.";
}
&::after {
clear: both;
content: "";
display: block;
}
}
// `grid-media` allows you to change your layout based on a media query.
/// For example, an object can span 3 columns on small screens and 6 columns
/// on large screens.
///
/// You can take this a step further and set different grid attributes like
/// gutter size and total column count for each media query. So, for example,
/// you can have a `1rem` gutter on small screens, and a `2rem` gutter on large
/// screens.
///
/// @group features
///
/// @name Grid media
///
/// @argument {map} $grid
/// The grid or grids to be used within the scope of the block.
/// These grids should include the `media` property to determine the expression
/// for the media query.
///
/// @content
/// Grid media will temporarily override the default grid with the attributes
/// of the custom grids. When `grid-media` is given a custom grid, it will
/// apply that grid to any of other Neat mixins within the `grid-media` block
/// (`{…}`). Once the mixin block has ended the default grid will revert to
/// its original state as defined by `$neat-grid`. This allows for different
/// gutter width and column count based on screen size or other properties.
///
/// If multiple grids are passed in to `grid-media`, it will loop through the
/// contents of the block, quickly allowing you to apply multiple grids in a
/// single mixin.
///
/// @example scss
/// $custom-neat-grid: (
/// columns: 12,
/// gutter: 50px,
/// media: "screen and (max-width: 999px)",
/// );
///
/// $custom-neat-grid-2: (
/// columns: 12,
/// gutter: 70px,
/// media: 1000px,
/// );
///
/// .element {
/// @include grid-column(3);
///
/// @include grid-media($custom-neat-grid, $custom-neat-grid-2){
/// @include grid-column(6);
/// }
/// }
///
/// @example css
/// .element {
/// width: calc(25% - 25px);
/// float: left;
/// margin-left: 20px;
/// }
///
/// @media only screen and (max-width: 999px) {
/// .element {
/// width: calc(50% - 75px);
/// float: left;
/// margin-left: 50px;
/// }
/// }
///
/// @media only screen and (min-width: 1000px) {
/// .element {
/// width: calc(50% - 75px);
/// float: left;
/// margin-left: 70px;
/// }
/// }
@mixin grid-media($grids...) {
@each $_grid in $grids {
$_media: _retrieve-neat-setting($_grid, media);
$_query: _neat-parse-media($_media);
@media #{$_query} {
$_default-neat-grid: $neat-grid;
$neat-grid: map-merge($neat-grid, $_grid) !global;
@content;
$neat-grid: $_default-neat-grid !global;
}
}
}
/// Push or pull a grid column by manipulating its left margin.
///
/// @group features
///
/// @name Grid push
///
/// @argument {number (unitless)} $push [false]
/// The number of columns to push the column.
///
/// @argument {map} $grid [$neat-grid]
/// The grid to be used to determine how far to push the column.
/// By default, the global `$neat-grid` will be used.
///
/// @example scss
/// .element {
/// @include grid-push(3);
/// }
///
/// @example css
/// .element {
/// margin-left: calc(25% - 25px + 40px);
/// }
@mixin grid-push($push: false, $grid: $neat-grid) {
$_grid-columns: _retrieve-neat-setting($grid, columns);
$_grid-gutter: _retrieve-neat-setting($grid, gutter);
@if $push {
$_gutter-affordance: $_grid-gutter * 2;
$_margin-value: calc(#{_neat-column-width($grid, $push)} + #{$_gutter-affordance});
margin-#{_neat-float-direction($grid)}: $_margin-value;
} @else {
$_margin-value: _retrieve-neat-setting($grid, gutter);
margin-#{_neat-float-direction($grid)}: $_margin-value;
}
}
/// Shift columns and reorder them within their container using relative
/// positioning.
///
/// @group features
///
/// @name Grid shift
///
/// @argument {number (unitless)} $shift [false]
/// The number of columns to shift the column.
///
/// @argument {map} $grid [$neat-grid]
/// The grid to be used to determine how far to shift the column.
/// By default, the global `$neat-grid` will be used.
///
/// @example scss
/// .element {
/// @include grid-shift(3);
/// }
///
/// @example css
/// .element {
/// left: calc(25% - 25px + 20px);
/// position: relative;
/// }
@mixin grid-shift($shift: false, $grid: $neat-grid) {
@if $shift {
$_shift-value: calc(#{_neat-column-width($grid, $shift)} + #{_retrieve-neat-setting($grid, gutter)});
#{_neat-float-direction($grid)}: $_shift-value;
} @else {
#{_neat-float-direction($grid)}: auto;
}
position: relative;
}
/// Creates a series of guide lines using the `background-image` property on a
/// grid container to visualise the columns and gutters of the grid.
///
/// @group features
///
/// @name Grid visual
///
/// @argument {color} $color
/// The color of the guide lines created.
///
/// @argument {map} $grid [$neat-grid]
/// The grid used to determine the guides
///
/// @example scss
/// .element {
/// @include grid-visual;
/// }
///
/// @example css
/// .element {
/// background-image: repeating-linear-gradient( … ) ;
/// }
@mixin grid-visual($color: null, $grid: $neat-grid) {
@if not $color {
$color: _retrieve-neat-setting($grid, color);
}
$_grid-columns: _retrieve-neat-setting($grid, columns);
$_grid-gutter: _retrieve-neat-setting($grid, gutter);
$_grid-visual-column: "#{_neat-column-width($grid, 1)} + #{$_grid-gutter}";
$_grid-visual:
transparent,
transparent $_grid-gutter,
$color $_grid-gutter,
$color calc(#{$_grid-visual-column}),
;
background-image: repeating-linear-gradient(to right, $_grid-visual);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment