Статьи

Создание Радужной Границы с Sass

Многие современные дизайны хорошо используют эффект разноцветной границы (который мы могли бы также назвать «радугой» или «полосатой» границей). Например, посмотрите на блог Treehouse — у него есть разноцветная рамка под навигацией, и он выглядит действительно красиво.

Цветная рамка на дереве

Однако, по моему мнению, Treehouse кодирует это неправильно. Поскольку это строго касается эстетики, это должно выполняться CSS — и только CSS — без необходимости дополнительной работы в HTML. Treehouse использует 50 элементов span

Whaaaat?

Излишне загружать такой большой объем элементов в DOM, чтобы вы могли создать полосатую рамку. Почему бы не использовать CSS для этого? Я имею в виду только CSS. Градиенты великолепны для этого типа задач! Да, вы можете создать несколько цветов с помощью CSS-градиентов, и это довольно легко сделать.

Единственное предостережение в том, что градиенты — это своего рода боль при написании. У них утомительный синтаксис, который может привести к опечаткам и ошибкам. Плюс необходимость повторять цветовые остановки для достижения нескольких цветов раздражает.

Sass на помощь!

Это то, о чем я писал в прошлом году о CSS-хитростях — но, оглядываясь назад на свой код, я подумал, что было бы неплохо пересмотреть все это, чтобы посмотреть, сможем ли мы добиться большего успеха, тем более что теперь у нас есть доступ к Sass 3.3 функции .

Прежде чем переходить к коду, давайте посмотрим, что мы хотим создать. Я вижу три разных способа получения этого эффекта:

  1. Одинаково широкие цветовые разделы на основе списка цветов.
  2. Цветные сечения нестандартного размера на основе двухмерного списка цветов + цветовые остановки.
  3. Цветовые секции произвольного размера на основе списка цветов со случайно сгенерированными цветовыми остановками.

То, что я хотел бы иметь, — это уникальная функция, которая зависит от «частных» функций в зависимости от случая, с которым мы сталкиваемся. Это делает API простым для пользователя и хорошо организованным кодом для разработчика (AKA you).

Основная функция

 @function stripes($colors, $direction: 90deg, $random: false) {
  // If lonely color
  @if length($colors) == 1 { @return $colors; }

  // Else
  $type: 'equal';

  @if $random {
    $type: 'random';
  }

  @else if length(nth($colors, 1)) > 1 {
    $type: 'custom';
  }

  @return linear-gradient($direction, call('_stripes-#{$type}-stops', $colors));
}

Вот что происходит: сначала мы проверяем, является ли переменная $colors Иначе, мы определяем случай, с которым мы сталкиваемся: randomcustomequal Если, как и я, вы предпочитаете троичные операторы, вот что вы можете сделать для того же результата:

 $type: if($random, 'random', if(length(nth($colors, 1)) > 1, 'custom', 'equal'));

Наконец, мы хорошо используем функцию call Это позволяет нам вызывать функцию, используя ее имя в виде строки, то есть мы можем динамически вызывать функцию с задержкой на основе определенного $type

Обратите внимание, что мы возвращаем linear-gradient()background: stripes($colors)

Примечание: если вы используете Sass 3.2 и не можете использовать функцию call@return

Одинаковые цветовые стопы

Что удивительно в синтаксисе linear-gradient() Это означает, что хорошо отформатированный список Sass может быть непосредственно введен в функцию градиента. Все, что нам нужно сделать, — это создать список, разделенный запятыми, где каждый элемент представляет собой список из двух элементов, разделенных цветом и ограничителем цвета. Например: red 10%, blue 10%

Теперь вернемся к нашей функции. Самый простой случай, безусловно, тот, где все цвета имеют одинаковую ширину. Чтобы определить эту ширину, все, что нам нужно сделать, это разделить 100% Затем мы перебираем список и строим чистый список для функции градиента.

 @function _stripes-equal-stops($colors) {
  $gradients: ();                                                        // 1
  $stops: 100% / length($colors);                                        // 2

  @for $i from 1 to length($colors) {                                    // 3
    $gradients: append($gradients, nth($colors, $i) $i * $stops, comma); // 4
    @if $i < length($colors) {                                        // 5
      $gradients: append($gradients, nth($colors, $i + 1) $i * $stops);  // 6
    }
  }

  @return $gradients;                                                    // 7
}

Это может выглядеть сложно, но на самом деле это очень просто. Вот что он делает:

  1. Создайте пустой список для наших цветов и цветовых остановок.
  2. Определите ширину цвета в процентах.
  3. Перебрать цвета.
  4. Добавьте цвет ( nth($colors, $i)$i * $stops$gradients
  5. Если в списке остался цвет, добавьте его так же, как мы это сделали.
  6. Наконец, верните список.

Например, рассмотрите список $colorsred, yellow, green Результат, возвращаемый функцией, будет red 33.33%, yellow 33.33%, yellow 66.66%, green 66.66%

Пользовательские Цветовые Остановки

Мы также можем принять двухмерный список цветов и цветовых остановок. Что-то вроде red 10%, blue 20%, green 60% Это означает, что красный цвет должен занимать 10% от общей ширины, синий — от 10% до 20%, а зеленый — от 20% до конца. Действительно, последняя остановка цвета не анализируется.

 @function _stripes-custom-stops($colors) {
  $gradients: ();

  @for $i from 1 to length($colors) {
    @if length(nth($colors, $i)) > 1 {
      $color: nth(nth($colors, $i), 1);
      $stop:  nth(nth($colors, $i), 2);

      $gradients: append($gradients, $color $stop, comma);
      @if $i < length($colors) {
        $gradients: append($gradients, nth(nth($colors, $i + 1), 1) $stop);
      }
    }

    @else {
      @warn '`#{nth($colors, $i)}` skipped because it is only one item long while it should be 2: (color, color-stop).';
    }
  }

  @return $gradients;
}

Код почти такой же, как в предыдущей функции, за исключением того, что вместо вычисления цветовой остановки мы читаем его из второго элемента индекса текущего цикла. Если для цвета не определена остановка цвета, мы предупреждаем пользователя, что цвет пропускается.

Случайные цветовые остановки

Наконец, мы можем случайным образом генерировать наши цветовые остановки. Возможно, вы заметили, что в примере Treehouse цвета не одинаковой ширины; некоторые короче, некоторые длиннее. Если мы хотим добиться подобного эффекта, мы могли бы вычислить цветовые остановки с помощью случайной функции.

Сначала я позволил судьбе решить, что цвета прекратятся, однако я очень часто сталкивался с массивным цветом, занимающим 90% ширины, а все остальные цвета изо всех сил пытались вписаться в оставшееся пространство. Это отстой! То, что я хотел, было цветами почти равного размера с небольшим изменением длины.

 @function _stripes-random-stops($colors) {
  @if length(nth($colors, 1)) > 1 {
    @return _stripes-custom-stops($colors);
  }

  $nb: length($colors);
  $gradients: ();
  $variation: 10;
  $median: 100 / $n;

  @for $i from 1 to $nb {
    $stop: $median * $i; 
    $random: rand($stop - $variation, $stop + $variation) * 1%;
    $gradients: append($gradients, nth($colors, $i) $random, comma);
    @if $i < length($colors) {
      $gradients: append($gradients, nth(nth($colors, $i + 1), 1) $random);
    } 
  }

  @return $gradients;
}

Практически тот же код, что и раньше. Но обратите внимание, как мы генерируем случайное число между n - 10%n + 10%n Это гарантирует, что все цветовые сечения будут примерно одинаковой ширины, не будучи строго одинаковыми, что приведет к аккуратному небольшому эффекту случайных размеров цветов.

И случайная функция в Sass 3.3, и пользовательская функция Ruby из CodePen принимают только один аргумент: максимальное значение для перехода между 1 и заданным значением. Поэтому, если мы хотим, чтобы функция генерировала случайные minmax

 @function rand($min, $max) {
  @return random($max - $min) + $min;
}

Заключительные слова + Демо

Таким образом, у вас есть чистая и лаконичная функция для создания разноцветной рамки из списка цветов. Как видите, код не так сложен для понимания и, в конце концов, хорошо организован. API довольно прост в использовании, так что я думаю, что мы его прибили!

Вы можете играть с кодом на CodePen: