2

我正在制作一个显示帐户交易的视图,并且我想对交易类型/状态进行颜色编码。我还想展示一个解释颜色代码的图例。

我想要一个结构如下的最终结果:

HTML

<table id="transactions">
  <thead>
    <tr>
      <th colspan="2">
        Transactions
      </th>
    </tr>
  </thead>
  <tbody>
    <tr class="credit">
      <td>A credit</td>
      <td>$1.00</td>
    </tr>
    <tr class="debit paid">
      <td>A paid debit</td>
      <td>($2.00)</td>
    </tr>
    <tr class="debit unpaid">
      <td>An unpaid debit</td>
      <td>($3.00)</td>
    </tr>
  </tbody>
</table>
<hr/>
<table id="legend">
  <thead>
    <tr>
      <th colspan="3">
        Legend
      </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="credit">Credit</td>
      <td class="debit paid">Paid</td>
      <td class="debit unpaid">Unpaid</td>
    </tr>
  </tbody>
</table>

CSS

table#transactions > tbody > tr.credit {
  color: limegreen;
}

table#legend > tbody > tr > td.credit {
  color: limegreen;
}

table#transactions > tbody > tr.debit.paid {
  color: goldenrod;
}

table#legend > tbody > tr > td.debit.paid {
  color: goldenrod;
}

table#transactions > tbody > tr.debit.unpaid {
  color: crimson;
}

table#legend > tbody > tr > td.debit.unpaid {
  color: crimson;
}

(代码笔)

请注意,“借方”使用两个类别名称,以将它们与贷方区分开来。

显然那里有一些冗余,我试图将其重构为这个(无效的)LESS 代码:

.transaction-status(@class, @color) {
  table#transactions > tbody > tr@{class} {
    color: @color;
  }

  table#legend > tbody > tr > td@{class} {
    color: @color;
  }  
}

.transaction-status(.credit, limegreen);
.transaction-status(.debit.paid, goldenrod);
.transaction-status(.debit.unpaid, crimson);

一种可能的解决方法是重新调整事物,以便不同的事务类型具有一个唯一的类名称,但这感觉就像时间旅行到 IE6 时代。即我知道,但想避免这个有效的 LESS,它看起来如此接近,但到目前为止:

.transaction-status(@class, @color) {
  table#transactions > tbody > tr.@{class} {
    color: @color;
  }

  table#legend > tbody > tr > td.@{class} {
    color: @color;
  }  
}

.transaction-status(credit, limegreen);
.transaction-status(debit-paid, goldenrod);
.transaction-status(debit-unpaid, crimson);

我尝试引用类名,但即使这使第一个 LESS 示例编译,引号也会传递给输出 CSS。那么,有没有办法将“标识符”以外的东西作为参数传递给LESS mixin,并让它在选择器插值中正确工作?

4

2 回答 2

2

Option 1:

As you mentioned, one option is to pass the value within quotes. But when that is done, you need to make sure to remove them before using them to perform selector interpolation. This can be done by either using the ~() or the e() built-in functions. Both of them will strip out the quotes from the input value. Once this is done, the temporary variable whose value doesnt have the quotes can be used for selector interpolation like below:

.transaction-status(@class, @color) {
    @className: ~"@{class}";
    table#transactions > tbody > tr@{className} {
        color: @color;
    }

    table#legend > tbody > tr > td@{className} {
        color: @color;
    }  
}

.transaction-status(".credit", limegreen);
.transaction-status(".debit.paid", goldenrod);
.transaction-status(".debit.unpaid", crimson);

Option 2: (a bit round about in my opinion)

You can also use the ... option to pass in as many classes as required (note that this needs a small change to the order in which the inputs are passed) and then convert it to a string and use the replace function to add the .. The replace function is required because the converted string would be of the format class1 class2 (space separator).

.transaction-status(@color, @class...) {
    @className: e(replace("@{class}" , " " , ".", 'g' )); 
    /* arguments: input string, pattern to match, replacement value, regex flags */
    table#transactions > tbody > tr.@{className} {
        color: @color;
    }

    table#legend > tbody > tr > td.@{className} {
        color: @color;
    }   
}

.transaction-status(limegreen, credit);
.transaction-status(goldenrod, debit, paid);
.transaction-status(crimson, debit, unpaid);

Note: Option 2 would work only with Less v.1.7.0 and above because the replace function was introduced only in v1.7.0.

于 2014-09-30T02:28:04.733 回答
2

It looks like you could color the whole row in either case? If so, a simple nesting of your selectors would reduce duplication, and arguably be easier to read:

table#transactions, table#legend {
    & > tbody > tr {
      &.credit {
        color: limegreen;
      }

      &.debit.paid {
        color: goldenrod;
      }

      &.debit.unpaid {
        color: crimson;
      }
    }
  }
}

But that doesn't let you easily reuse these class/color combinations in other parts of your code, which is something that you very well may want to do. I would define your color classes more like this:

.trans-status {
  &.credit {
    color: limegreen;
  }

  &.debit.paid {
    color: goldenrod;
  }

  &.debit.unpaid {
    color: crimson;
  }
}

And then you can apply the appropriate classes with more precision:

<tr>
  <td>An unpaid debit</td>
  <td class="trans-status debit unpaid">($3.00)</td>
</tr>

Here's a fork of your example using this approach:

https://codepen.io/anon/pen/mxMLPG

Another advantage to using this approach, is that you can also apply these styles as mixins in your Less files. For example, if you needed to use the same color values in other parts of your code, you could define the colors more abstractly, and apply them in different ways:

.status {
  .success {
    color: limegreen;
  }

  .confirmed {
    color: goldenrod;
  }

  .warning {
    color: crimson;
  }
}

.negative-balance {
  .status.warning;
}

#rewards-points {
  .status.success;
}

It's also worth noting that in cases where you do need to pass rules/mixins into other mixins, Less 1.7.0 and above supports Detatched Rulesets to accomplish this same sort of thing with a cleaner syntax than string interpolation. The original question doesn't really warrant this level of complexity, but it can be useful for things like breakpoints:

.break(@min-width; @max-width; @rules) {
  @media only screen and (min-width:@min-width) 
    and (max-width: @max-width){
    @rules();
  }
}

.break(0px, 480px, {
  font-size: 10px;
  padding: 8px;
});
于 2018-03-24T15:38:12.210 回答