rfs
Version:
Powerful & easy-to-use responsive resizing engine.
242 lines (185 loc) • 7.01 kB
text/less
// stylelint-disable selector-max-combinators, selector-max-compound-selectors
// Less RFS mixin
//
// Automated responsive values for font sizes, paddings, margins and much more
//
// See https://github.com/twbs/rfs
// Configuration
// Base value
@rfs-base-value: 1.25rem;
@rfs-unit: rem;
// Breakpoint at where value stops increasing
@rfs-breakpoint: 1200px;
@rfs-breakpoint-unit: px;
// Resize value based on screen height and width
@rfs-two-dimensional: false;
// Factor of decrease
@rfs-factor: 10;
// Mode. Possibilities: "min-media-query", "max-media-query"
@rfs-mode: "min-media-query";
// Generate enable or disable classes. Possibilities: false, "enable" or "disable"
@rfs-class: false;
// 1 rem = @rfs-rem-value px
@rfs-rem-value: 16;
// Safari iframe resize bug: https://github.com/twbs/rfs/issues/14
@rfs-safari-iframe-resize-bug-fix: false;
// Disable RFS by setting @enable-rfs to false
@enable-rfs: true;
// RFS mixin
.rfs(@values, @property: font-size) {
._rfs-calculate(1, ~"", ~"");
}
// Recursive calculate mixin
._rfs-calculate(@index, @valueResult, @fluidValueResult) {
& when (@index <= length(@values)) {
@currentValue: if(extract(@values, @index) = important, ~"!important" , extract(@values, @index));
@space: if(@index = length(@values), ~"", ~" ");
& when (not(isunit(@currentValue, px)) and not(isunit(@currentValue, rem))) {
._rfs-calculate((@index + 1), ~"@{valueResult}@{currentValue}@{space}", ~"@{fluidValueResult}@{currentValue}@{space}");
}
& when ((isunit(@currentValue, px)) or (isunit(@currentValue, rem))) {
@val: if(isunit(@currentValue, rem), unit((@currentValue * @rfs-rem-value)), unit(@currentValue));
// Remove unit if zero
@value-unit: if(@val = 0, ~"", @rfs-unit);
@renderedValue: unit(if(@rfs-unit = px, @val, ((@val / @rfs-rem-value))), @value-unit);
@rfs-min: if(isunit(@rfs-base-value, rem), unit((@rfs-base-value * @rfs-rem-value)), unit(@rfs-base-value));
& when (not((abs(@val) > @rfs-min) and (@rfs-factor > 1) and (@enable-rfs = true))) {
._rfs-calculate((@index + 1), ~"@{valueResult}@{renderedValue}@{space}", ~"@{fluidValueResult}@{renderedValue}@{space}");
}
& when ((abs(@val) > @rfs-min) and (@rfs-factor > 1) and (@enable-rfs = true)) {
@breakpoint: if(isunit(@rfs-breakpoint, em) or isunit(@rfs-breakpoint, rem), unit((@rfs-breakpoint * @rfs-rem-value)), unit(@rfs-breakpoint));
@max-width: unit(if(@rfs-breakpoint-unit = px, @breakpoint, ((@breakpoint / @rfs-rem-value))), @rfs-breakpoint-unit);
// Calculate minimum value
@value-min: @rfs-min + (((abs(@val) - @rfs-min) / @rfs-factor));
// Calculate difference between @val and the minimum value
// Rounding needed to prevent rounding errors
@value-variable-width: unit(round(((abs(@val) - @value-min) / ((@breakpoint / 100))), 15), if(@rfs-two-dimensional, vmin, vw));
& when (@val > 0) {
@renderedFluidValue: calc(unit(if(@rfs-unit = px, ((@value-min)), ((@value-min / @rfs-rem-value))), @rfs-unit) ~"+" @value-variable-width);
._rfs-calculate((@index + 1), ~"@{valueResult}@{renderedValue}@{space}", ~"@{fluidValueResult}@{renderedFluidValue}@{space}");
}
& when (@val < 0) {
@renderedFluidValue: calc(unit(if(@rfs-unit = px, ((-@value-min)), ((-@value-min / @rfs-rem-value))), @rfs-unit) ~"-" @value-variable-width);
._rfs-calculate((@index + 1), ~"@{valueResult}@{renderedValue}@{space}", ~"@{fluidValueResult}@{renderedFluidValue}@{space}");
}
}
}
}
& when (@index > length(@values)) {
@fluidValue: @fluidValueResult;
& when (@valueResult = @fluidValueResult) {
@{property}: @valueResult;
}
& when (not(@valueResult = @fluidValueResult)) {
& when (@rfs-class = "disable") and (@rfs-mode = "max-media-query") {
&,
.disable-rfs &,
&.disable-rfs {
@{property}: @valueResult;
}
}
& when (@rfs-class = "enable") and (@rfs-mode = "min-media-query") {
@{property}: @valueResult;
.enable-rfs &,
&.enable-rfs {
@{property}: @fluidValue;
}
}
& when (not((@rfs-class = "disable") and (@rfs-mode = "max-media-query"))) and not((@rfs-class = "enable") and (@rfs-mode = "min-media-query")) {
@{property}: if(@rfs-mode = "min-media-query", @fluidValue, @valueResult);
}
// Media query
& when (@rfs-class = "enable") {
.enable-rfs &,
&.enable-rfs {
._rfs-render-media-query();
}
}
& when (@rfs-class = "disable") and (@rfs-mode = "min-media-query") {
.disable-rfs &,
&.disable-rfs {
@{property}: @valueResult;
}
._rfs-render-media-query();
}
& when (not(@rfs-class = "enable")) and not(@rfs-class = "disable") {
._rfs-render-media-query();
}
& when ((@rfs-safari-iframe-resize-bug-fix)) {
// stylelint-disable-next-line length-zero-no-unit
min-width: 0vw;
}
}
}
}
._rfs-render-media-query () {
& when (@rfs-two-dimensional) {
& when (@rfs-mode = "min-media-query") {
@media (min-width: @max-width) and (min-height: @max-width) {
@{property}: @valueResult;
}
}
& when (@rfs-mode = "max-media-query") {
@media (max-width: @max-width), (max-height: @max-width) {
@{property}: @fluidValue;
}
}
}
& when (not(@rfs-two-dimensional)) {
& when (@rfs-mode = "min-media-query") {
@media (min-width: @max-width) {
@{property}: @valueResult;
}
}
& when (@rfs-mode = "max-media-query") {
@media (max-width: @max-width) {
@{property}: @fluidValue;
}
}
}
}
._rfs-render-media-query-content() {
& when (@rfs-class = "enable") {
.enable-rfs &,
&.enable-rfs {
@{property}: if(@rfs-mode = "min-media-query", @valueResult, @fluidValue);
}
}
& when (not(@rfs-class = "enable")) {
@{property}: if(@rfs-mode = "min-media-query", @valueResult, @fluidValue);
}
}
// Sharthand mixins
.font-size(@value) {
.rfs(@value);
}
.padding(@value, @property: padding) {
.rfs(@value, @property);
}
.padding-top(@value, @property: padding-top) {
.rfs(@value, @property);
}
.padding-right(@value, @property: padding-right) {
.rfs(@value, @property);
}
.padding-bottom(@value, @property: padding-bottom) {
.rfs(@value, @property);
}
.padding-left(@value, @property: padding-left) {
.rfs(@value, @property);
}
.margin(@value, @property: margin) {
.rfs(@value, @property);
}
.margin-top(@value, @property: margin-top) {
.rfs(@value, @property);
}
.margin-right(@value, @property: margin-right) {
.rfs(@value, @property);
}
.margin-bottom(@value, @property: margin-bottom) {
.rfs(@value, @property);
}
.margin-left(@value, @property: margin-left) {
.rfs(@value, @property);
}