Repeat dots in LESS / SASS for Content property

2020-04-07 19:10发布

问题:

Take a look at below CSS styles and i'm planning to use LESS & SASS for two different projects and is this possible in preprocessors.

.longDots {
  content: "  ......................................................................................................";
}

.shortDots {
  content: "....................";
}

What exactly, I want to do to avoid repeated dots to have it as single dot and that too configurable to change it as -, #, *

Something mixin like below.

 .longDots {
    content: repeater('.', 25);
}

.shortDots {
    content: repeater('.', 10);
}

.longDashes {
    content: repeater('-', 25);
}

.shortDashes {
    content: repeater('-', 10);
}

回答1:

I do a mixin in SASS, in LESS I think you can do something similar. Some characthers like points or dashes must be between quotation marks.

SASS

@mixin repeat($character, $n){
  $c:"";
  @for $i from 1 through $n {
    $c: $c + $character;
 }
   content: $c;
}

.dash{
  @include repeat("-", 4)
}

.dot{
  @include repeat(".", 6)
}

.letter{
  @include repeat(x, 2)
}

OUTPUT

.dash {
  content: "----";
}

.dot {
  content: "......";
}

.letter {
  content: "xx";
}

Or you can do also a function:

SASS

@function repeat($character, $n){
  $c:"";
  @for $i from 1 through $n {
    $c: $c + $character;
 }
    @return $c;
}

.dash{
  content: repeat("-", 4)
}

.dot{
  content: repeat(".", 6)
}

OUTPUT

.dash {
  content: "----";
}

.dot {
  content: "......";
}


In LESS there isn't for sentences and I can't found a clean way to do but this code works (the output is quite dirty):

LESS

.repeat(@char, @i) when (@i> 0) {
   .repeat(@char, (@i - 1)); 
  content+_:"@{char}";
}

.dash {
  .repeat("-" ,3);
}

.dot {
  .repeat("." ,5);
}

OUTPUT

.dash {
  content: "-" "-" "-";
}
.dot {
  content: "." "." "." "." ".";
}


回答2:

You could do something like:

SASS

@mixin repeater($item, $count) {
    $string: "";
    @for $i from 1 through $count {
        $string: $string + $item;
    }
    content: $string;
}

.longDots {
    @include repeater('.', 25);
}

.shortDots {
    @include repeater('.', 10);
}

.longDashes {
    @include repeater('-', 25);
}

.shortDashes {
    @include repeater('-', 10);
}

The mixin could also be written like:

@mixin repeater($item, $count) {
    $string: "";
    @for $i from 1 through $count {
        $string: str-insert($string, $item, $i - 1);
    }
    content: $string;
}

or:

@mixin repeater($item, $count) {
    $string: "";
    @while $count > 0 {
        $string: $string + $item;
        $count: $count - 1;
    }
    content: $string;
}

or:

@mixin repeater($item, $count) {
    $string: "";
    @while $count > 0 {
        $string: str-insert($string, $item, $count);
        $count: $count - 1;
    }
    content: $string;
}

Whatever appeals more to you.

You can always test your small parts of SASS online at e.g. http://sass.js.org/ or http://www.sassmeister.com/, if you don't have lokal tools for that.



For LESS you need a little bit more complex mixins:

.contentresult(@string, @count) when (@count = 1) {
    content: @string
}

.repeater(@item, @count, @string: "") when (@count > 0) {
    .repeater(@item, (@count - 1), "@{string}@{item}");
    .contentresult("@{string}@{item}", @count);
}

.longDots {
    .repeater('.', 25);
}

.shortDots {
    .repeater('.', 10);
}

.longDashes {
    .repeater('-', 25);
}

.shortDashes {
    .repeater('-', 10);
}

The first mixin is an if-statement, the second one is the actual loop. It's important to use these two separate mixins, because only the repeater mixin would produce a lot of content properties for each iteration with the shortest at the bottom unfortunately.

Tested with http://less2css.org/. (It compiles successfully with LESS version 1.3.3 and later.)




Since OP updated his question:

SASS

@function repeater($item, $count) {
    $string: "";
    @for $i from 1 through $count {
        $string: $string + $item;
    }
    @return "#{$string}";
}

.longDots {
    content: repeater('.', 25);
}

With "#{$string}" I'm just showing you another way of accessing the content of a variable. You could also just use $string. Every mixin I showed you earlier is working once you turn it into a function the way I did here.

LESS

.contentresult(@string, @count) when (@count = 1) {
    @return: @string
}

.repeater(@item, @count, @string: "") when (@count > 0) {
    .repeater(@item, (@count - 1), "@{string}@{item}");
    .contentresult("@{string}@{item}", @count);
}

.longDots {
    .repeater('.', 25);
    content: @return;
}


回答3:

LESS

Based on Seika85's answer, I've created a more generalized function for repeating an input arg with your choice of delimiter:

.repeater(@item, @count, @delimiter: " ", @iterated-item: "") when (@count = 1) {
  @return: ~'@{iterated-item}@{item}';
}
.repeater(@item, @count, @delimiter: " ", @iterated-item: "") when (@count > 1) {
  .repeater(@item, (@count - 1), @delimiter, ~'@{iterated-item}@{item}@{delimiter}');
}

Usage:

div {
  background-image: .repeater(url(foo.svg), 5, ", ")[];
}

Compiles to:

div {
  background-image: url(foo.svg), url(foo.svg), url(foo.svg), url(foo.svg), url(foo.svg);
}