Skip to content

Instantly share code, notes, and snippets.

@tjbenton
Created April 14, 2015 17:37
Show Gist options
  • Save tjbenton/5a80be99f082b09ce8b9 to your computer and use it in GitHub Desktop.
Save tjbenton/5a80be99f082b09ce8b9 to your computer and use it in GitHub Desktop.
Generated by SassMeister.com.
// ----
// Sass (v3.4.12)
// Compass (v1.0.3)
// ----
// _ _ _ _ _
// (_) | | | | | (_)
// _ _ __ ___| |_ _ __| | ___ _ __ ___ ___ __| |_ __ _
// | | '_ \ / __| | | | |/ _` |/ _ \ | '_ ` _ \ / _ \/ _` | |/ _` |
// | | | | | (__| | |_| | (_| | __/ | | | | | | __/ (_| | | (_| |
// |_|_| |_|\___|_|\__,_|\__,_|\___| |_| |_| |_|\___|\__,_|_|\__,_|
//
// Simple, elegant and maintainable media queries in Sass
//
// http://include-media.com
//
// Author: Eduardo Boucas <mail@eduardoboucas.com>
//
///
/// Creates a list of global breakpoints
///
/// @author Eduardo Boucas
///
/// @example scss - Creates a single breakpoint with the label `phone`
/// $breakpoints: ("phone": 320px);
///
$breakpoints: ("phone": 320px, "tablet": 768px, "desktop": 1024px) !default;
///
/// Creates a list of static expressions or media types
///
/// @author Eduardo Boucas
///
/// @example scss - Creates a single media type (screen)
/// $media-expressions: ("screen": "screen");
///
/// @example scss - Creates a static expression with logical disjunction (OR operator)
/// $media-expressions: (
/// "retina2x": (
/// "(-webkit-min-device-pixel-ratio: 2)",
/// "(min-resolution: 192dpi)"
/// )
/// );
///
$media-expressions: ("screen": "screen", "print": "print", "handheld": "handheld", "retina2x": ("(-webkit-min-device-pixel-ratio: 2)", "(min-resolution: 192dpi)"), "retina3x": ("(-webkit-min-device-pixel-ratio: 3)", "(min-resolution: 350dpi)")) !default;
///
/// Defines a number to be added or subtracted from each unit when declaring breakpoints with exclusive intervals
///
/// @author Eduardo Boucas
///
/// @example scss - Interval for pixels is defined as `1` by default
/// @include media(">128px"){}
///
/// /* Generates: */
/// @media (min-width: 129px){}
///
/// @example scss - Interval for ems is defined as `0.01` by default
/// @include media(">20em"){}
///
/// /* Generates: */
/// @media (min-width: 20.01em){}
///
/// @example scss - Interval for rems is defined as `0.1` by default, to be used with `font-size: 62.5%;`
/// @include media(">2.0rem"){}
///
/// /* Generates: */
/// @media (min-width: 2.1rem){}
///
$unit-intervals: ("px": 1, "em": 0.01, "rem": 0.1) !default;
///
/// Generates a media query based on a list of conditions
///
/// @author Eduardo Boucas
///
/// @param{List} $conditions - Media query conditions
///
/// @example scss - With a single set breakpoint
/// @include media(">phone"){ }
///
/// @example scss - With two set breakpoints
/// @include media(">phone", "<=tablet"){ }
///
/// @example scss - With custom values
/// @include media(">=358px", "<850px"){ }
///
/// @example scss - With set breakpoints with custom values
/// @include media(">desktop", "<=1350px"){ }
///
/// @example scss - With a static expression
/// @include media("retina2x"){ }
///
/// @example scss - Do something for each condition
/// @include media("each", "", ">=phone", ">=tablet", retina){
/// .#{$media}foo{ // use $media to get the name of the breakpoint
/// background: black;
/// }
/// }
///
/// @example scss - Do something for each breakpoint in `$breakpoints`
/// @include media("each", "breakpoint"){
/// .#{$media}foo{
/// background: black;
/// }
/// }
///
/// @example scss - Mixing everything
/// @include media(">=350px", "<tablet", "retina3x"){ }
///
@mixin media($conditions...){
$media: "" !global; // resets $media to be "" each time it's called so it doesn't interfere with other media calls
@if nth($conditions, 1) == "each"{
$_breakpoint: nth($conditions, 2);
$_breakpoint-index: str-index($_breakpoint, "breakpoint");
@if $_breakpoint-index != null{
@if $_breakpoint-index == 1{ // if the dimention and operator aren't set
$_breakpoint: "width>=breakpoint";
}
$_breakpoint-parsed: parse-expression($_breakpoint);
$conditions: set-nth($conditions, 2, "");
@each $key, $value in $breakpoints{ // loops through each breakpoint name and prepends "<=" to it.
$conditions: append($conditions, "" + map-get($_breakpoint-parsed, dimension) + map-get($_breakpoint-parsed, operator) + $key, "comma");
}
}
@for $i from 2 through length($conditions){
$condition: nth($conditions, $i);
$name: map-get(parse-expression($condition), value);
@include media(nth($conditions, $i)){
$media: if($name == "", "", "#{$name}-") !global;
@content;
}
}
}@else{
@for $i from 1 through length($conditions){
$conditions: set-nth($conditions, $i, map-get(parse-expression(nth($conditions, $i)), expression));
}
$branches: get-query-branches($conditions);
$query: "";
@each $branch in $branches{
@if (str-length($query) != 0){
$query: $query + ", ";
}
$query: $query + $branch;
}
@if $query == ""{
@content;
}@else{
@media #{$query}{
@content;
}
}
}
}
///
/// Reads a list of media query expressions and separates logical disjunctions into different branches
///
/// @author Eduardo Boucas
///
/// @param{List} $expressions - list of expressions
///
/// @throws `$expression` is not a valid expression
///
/// @return{List | Null}
///
@function get-query-branches($expressions){
$result: "";
$has-groups: false;
// Getting initial snapshot and looking for groups
@each $expression in $expressions{
@if (str-length($result) != 0){
$result: $result + " and ";
}
@if (type-of($expression) == "string"){
$result: $result + $expression;
}
@else if (type-of($expression) == "list"){
$result: $result + nth($expression, 1);
$has-groups: true;
}
@else{
@warn "#{$expression} is not a valid expression.";
}
}
// If we have groups, we have to create all possible combinations
@if $has-groups{
@each $expression in $expressions{
@if (type-of($expression) == "list"){
$first: nth($expression, 1);
@each $member in $expression{
@if ($member != $first){
@each $partial in $result{
$result: join($result, str-replace-first($first, $member, $partial));
}
}
}
}
}
}
@return $result;
}
///
/// Parses a string to form a media query expression
///
/// @author Eduardo Boucas
///
/// @param{String} $expression - expression (in string)
///
/// @throws Expression with type `type-of($expression)` detected, string expected
/// @throws `$expression` is missing an operator
/// @throws Unknown unit: `$unit`
///
/// @return{String | Null}
///
@function parse-expression($expression){
$operator: "";
$value: "";
$element: "";
$result: "";
$is-value: true;
$dimension: "width";
@if (type-of($expression) != "string"){
@warn "Expression with type `#{type-of($expression)}` detected, string expected.";
}
@if $expression != ""{
// Detecting the "height" prefix
@if (str-slice($expression, 1, 6) == "height"){
$dimension: "height";
$expression: str-slice($expression, 7);
}
// Detecting (and ignoring) the "width" prefix for consistency
@if (str-slice($expression, 1, 5) == "width"){
$expression: str-slice($expression, 6);
}
// Separating the operator from the rest of the expression
@if (str-slice($expression, 2, 2) == "="){
$operator: str-slice($expression, 1, 2);
$value: str-slice($expression, 3);
}@else{
$operator: str-slice($expression, 1, 1);
$value: str-slice($expression, 2);
}
@debug $expression;
// Checking what type of expression we're dealing with
@if map-has-key($breakpoints, $value){
$result: map-get($breakpoints, $value);
}@else if map-has-key($media-expressions, $expression){
$result: map-get($media-expressions, $expression);
$value: $expression;
$is-value: false;
}@else if str-index($expression, "breakpoint") != null{
$result: "multiple breakpoints";
$is-value: false;
}@else{
$result: to-number($value);
}
@if ($is-value){
$unit: unit($result);
$interval: 0;
@if (map-has-key($unit-intervals, $unit)){
$interval: map-get($unit-intervals, $unit);
}@else{
@warn "Unknown unit: #{$unit}";
}
@if ($operator == ">"){
$element: "(min-#{$dimension}: #{$result + $interval})";
}@else if ($operator == "<"){
$element: "(max-#{$dimension}: #{$result - $interval})";
}@else if ($operator == ">="){
$element: "(min-#{$dimension}: #{$result})";
}@else if ($operator == "<="){
$element: "(max-#{$dimension}: #{$result})";
}@else{
@warn "#{$expression} is missing an operator.";
}
}@else{
$element: $result;
}
}
@return (
expression: $element,
operator: $operator,
dimension: $dimension,
value: $value
);
}
///
/// Replaces the first occurence of the string with the replacement string
///
/// @author Eduardo Boucas
///
/// @param{String} $search - The value being searched for
/// @param{String} $replace - The replacement string
/// @param{String} $subject - The string being replaced on
///
/// @return{String | Null}
///
@function str-replace-first($search, $replace, $subject){
$search-start: str-index($subject, $search);
@if $search-start == null{
@return $subject;
}
$result: str-slice($subject, 0, $search-start - 1);
$result: $result + $replace;
$result: $result + str-slice($subject, $search-start + str-length($search));
@return $result;
}
///
/// Casts a number to a string
///
/// @author Hugo Giraudel
///
/// @param{String} $string - Number to be parsed
///
/// @return{List | Null}
///
@function to-number($string){
// Matrices
$strings: "0" "1" "2" "3" "4" "5" "6" "7" "8" "9";
$numbers: 0 1 2 3 4 5 6 7 8 9;
// Result
$result: 0;
$divider: 0;
$minus: false;
// Looping through all characters
@for $i from 1 through str-length($string){
$character: str-slice($string, $i, $i);
$index: index($strings, $character);
@if $character == "-"{
$minus: true;
}
@else if $character == "."{
$divider: 1;
}@else{
@if type-of($index) != "number"{
$result: if($minus, $result * -1, $result);
@return _length($result, str-slice($string, $i));
}
$number: nth($numbers, $index);
@if $divider == 0{
$result: $result * 10;
}@else{
// Move the decimal dot to the left
$divider: $divider * 10;
$number: $number / $divider;
}
$result: $result + $number;
}
}
@return if($minus, $result * -1, $result);
}
@function _length($number, $unit){
$strings: "px" "cm" "mm" "%" "ch" "pica" "in" "em" "rem" "pt" "pc" "ex" "vw" "vh" "vmin" "vmax";
$units: 1px 1cm 1mm 1% 1ch 1pica 1in 1em 1rem 1pt 1pc 1ex 1vw 1vh 1vmin 1vmax;
$index: index($strings, $unit);
@if type-of($index) != "number"{
@warn "Unknown unit `#{$unit}`.";
@return false;
}
@return $number * nth($units, $index);
}
/*
test 1
*/
@include media("each", "breakpoint"){
.#{$media}foo{
background: black;
}
}
/*
test 2
*/
@include media("each", "height>=breakpoint"){
.#{$media}bar{
background: red;
}
}
/*
test 3
*/
@include media("each", "" ,">=phone", "<=tablet"){
.#{$media}qux{
background: pink;
}
}
/*
test 1
*/
.foo {
background: black;
}
@media (min-width: 320px) {
.phone-foo {
background: black;
}
}
@media (min-width: 768px) {
.tablet-foo {
background: black;
}
}
@media (min-width: 1024px) {
.desktop-foo {
background: black;
}
}
/*
test 2
*/
.bar {
background: red;
}
@media (min-height: 320px) {
.phone-bar {
background: red;
}
}
@media (min-height: 768px) {
.tablet-bar {
background: red;
}
}
@media (min-height: 1024px) {
.desktop-bar {
background: red;
}
}
/*
test 3
*/
.qux {
background: pink;
}
@media (min-width: 320px) {
.phone-qux {
background: pink;
}
}
@media (max-width: 768px) {
.tablet-qux {
background: pink;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment