直接在自定义中指定悬停颜色 Bootstrap 4

Specify hover colours directly in customized Bootstrap 4

我使用的是 Bootstrap 4.5.3 的自定义版本,并进行了一些相当简单的更改。

这是我的自定义 SCSS:

$newcolor1: #00a89c;
$newcolor2: #e61b53;

$colors: (
    "newcolor1": $newcolor1,
    "newcolor2": $newcolor2
);

$primary:   $newcolor1;

$theme-colors: (
    "primary": $primary,
    "newcolor2": $newcolor2
);

@import "bootstrap";

我要添加两种新颜色,将“primary”设置为 newcolor1,并为 newcolor2 添加主题,这样我就可以做,例如btn-newcolor2.

Bootstrap 自动计算这些颜色的变体以用于悬停、焦点等,这对我来说很好,但我的客户想直接指定悬停颜色,这让我超出了我非常有限的范围Sass知识。

查看源文件,似乎 Bootstrap 将基色按固定百分比加深以创建悬停版本。有没有办法强制它为 .btn-primary:hover 和 .btn-newcolor2:hover 使用特定颜色?理想的情况是,如果我能让它在我提供的地方使用指定的颜色,并在我没有提供的地方使用默认行为(按固定百分比变暗)。

用于生成按钮 css 颜色状态的 mixin 称为 button-variant(),它位于 bootstrap/scss/mixins.

此 sass mixin 确实具有处理自定义 .btn 悬停和活动颜色状态的参数能力...

@mixin button-variant(
  $background, 
  $border, 
  $hover-background: darken($background, 7.5%), 
  $hover-border: darken($border, 10%),
  $active-background: darken($background, 10%),
  $active-border: darken($border, 12.5%)
) { 
  //...
}

但是正如您所见,悬停和活动参数是 $default: 参数,使用 sass colour darken() function 作为值来计算传递的 $theme-colors 颜色值,以自动为状态生成颜色。

这使得仅使用 $theme-colors.

无法处理按钮状态颜色


There are a few ways to customise the .btn active and hover state colours whilst minimising compiled css and avoiding duplicate/overriding selectors in compiled css output.

第一种方法(最简单)

请参阅下面的 scss,其中单独处理 bootstrap 供应商 @imports 并以正确的顺序处理自定义 varsmap-removals,因此 bootstrap 正确编译和使用变量。

关注 scss 中的评论,这样您就知道发生了什么...

// import initial bootstrap vendors

@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins";

// remove unused default bootstrap colours from bs colour maps to prevent larger compiled css file sizes
// this will also speed up compiling time as you are not generating css for all bootstrap standard colours
// if you wish to keep some standard bootstrap colours then remove the ones you want to keep from the map-remove lists below

$colors: map-remove($colors, "blue","indigo","purple","pink","red","orange","yellow","green","teal","cyan","white","gray","gray-dark");
$grays: map-remove($grays, "100","200","300","400","500","600","700","800","900");
$theme-colors: map-remove($theme-colors, "primary","secondary","success","danger","warning","info","light","dark");

// use sass @debug to check dump logs of your colour maps after modifying them if you wish...

// @debug $colors;
// @debug $grays;
// @debug $theme-colors;

// now add your custom colour variables

$new-color-1: #00a89c;
$new-color-2: #e61b53;

// now add your custom colour maps using above variables

$colors: (
  "newcolor1": $new-color-1,
  "newcolor2": $new-color-2
);

// you can always tidy this up by including these variables and any other bootstrap theming override variables into a separate sass _vars.scss file
// and then import _vars.scss here (before root.scss and after mixins.scss|map-removals)...

//@import "./vars";

// now import the rest of your needed bootstrap scss vendor files below this
// the below imports will now use any variable overrides you've defined above

// if you want to reduce you css output file size and speed up compiling
// you can remove unused scss vendor imports below, for example i've removed breadcrumb, toasts and carousel

@import "~bootstrap/scss/root";
@import "~bootstrap/scss/reboot";
@import "~bootstrap/scss/type";
@import "~bootstrap/scss/images";
@import "~bootstrap/scss/code";
@import "~bootstrap/scss/grid";
@import "~bootstrap/scss/tables";
@import "~bootstrap/scss/forms";
@import "~bootstrap/scss/buttons";
@import "~bootstrap/scss/transitions";
@import "~bootstrap/scss/dropdown";
@import "~bootstrap/scss/button-group";
@import "~bootstrap/scss/input-group";
@import "~bootstrap/scss/custom-forms";
@import "~bootstrap/scss/nav";
@import "~bootstrap/scss/navbar";
@import "~bootstrap/scss/card";
//@import "~bootstrap/scss/breadcrumb";
@import "~bootstrap/scss/pagination";
@import "~bootstrap/scss/badge";
@import "~bootstrap/scss/jumbotron";
@import "~bootstrap/scss/alert";
@import "~bootstrap/scss/progress";
@import "~bootstrap/scss/media";
@import "~bootstrap/scss/list-group";
@import "~bootstrap/scss/close";
//@import "~bootstrap/scss/toasts";
@import "~bootstrap/scss/modal";
@import "~bootstrap/scss/tooltip";
@import "~bootstrap/scss/popover";
//@import "~bootstrap/scss/carousel";
@import "~bootstrap/scss/spinners";
@import "~bootstrap/scss/utilities";
@import "~bootstrap/scss/print";

因为我们清空了 $theme-colors 映射,bootstrap 将不会编译使用 $theme-colors@each 循环,因为它现在是空的。

我们现在可以在任何 .btn-* 选择器中手动使用 button-variant() mixin 来创建自定义按钮,而无需向编译输出添加额外的 css。

此选项最简单,因为您可以将任何颜色传递给 button-variant() 参数。

.btn-primary {
  @include button-variant(
    $new-color-1, // background
    $new-color-1, // border
    $new-color-1, // hover background (customise how you wish)
    $new-color-1, // hover border (customise how you wish)
    $new-color-1, // active background (customise how you wish)
    $new-color-1 // active border (customise how you wish)
  );
}

.btn-secondary {
  @include button-variant(
    $new-color-2, // background
    $new-color-2, // border
    $new-color-2, // hover background (customise how you wish)
    $new-color-2, // hover border (customise how you wish)
    $new-color-2, // active background (customise how you wish)
    $new-color-2 // active border (customise how you wish)
  );
}



第二种方法(更复杂)

利用上面的代码,在mixins.scss.

中重新引入$theme-colors和modify/override的@include button-variant()

在继续之前从上面的代码中删除了自定义按钮选择器。

此方法更难以精确控制悬停和活动状态颜色,因为 @include button-variant() 将对每个传递的颜色使用相同的参数 scss 颜色调整。

您可以试试这个...在 root.scss 之前和 $colors 地图数组之后立即重新引入 $theme-colors

$theme-colors: (
  "primary": $new-color-1,
  "secondary": $new-color-2
);

然后创建一个覆盖按钮混合来处理所有按钮变体调用。

@import "~bootstrap/scss/mixins"; 之后和 map-removals.

之前添加此 bootstrap v4.5.3 修改后的按钮变体 mixin

您可以将其放入项目中名为 _mixins.scss 的 sass 文件中,然后像这样导入 @import "./mixins"; 以保持整洁。

您也可以将此项目的所有自定义 mixins 也保存在“./mixins”中。

现在我们可以修改自定义 @mixin button-variant() 参数来处理传递的 $theme-colors.

// i've customised params in the button-variant() mixin below as an example
// see original default mixin params as comments below

// $background
// $border
// $hover-background: darken($background, 7.5%)
// $hover-border: darken($border, 10%) 
// $active-background: darken($background, 10%)
// $active-border: darken($border, 12.5%)

@mixin button-variant(
  $background,
  $border,
  $hover-background: lighten($background, 10%),
  $hover-border: lighten($border, 10%),
  $active-background: lighten($background, 2.5%),
  $active-border: lighten($border, 2.5%)
) {
  color: color-yiq($background);
  @include gradient-bg($background);
  border-color: $border;
  @include box-shadow($btn-box-shadow);

  @include hover() {
    color: color-yiq($hover-background);
    @include gradient-bg($hover-background);
    border-color: $hover-border;
  }

  &:focus,
  &.focus {
    color: color-yiq($hover-background);
    @include gradient-bg($hover-background);
    border-color: $hover-border;
    @if $enable-shadows {
      @include box-shadow($btn-box-shadow, 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5));
    } @else {
      // Avoid using mixin so we can pass custom focus shadow properly
      box-shadow: 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5);
    }
  }

  // Disabled comes first so active can properly restyle
  &.disabled,
  &:disabled {
    color: color-yiq($background);
    background-color: $background;
    border-color: $border;
    // Remove CSS gradients if they're enabled
    @if $enable-gradients {
      background-image: none;
    }
  }

  &:not(:disabled):not(.disabled):active,
  &:not(:disabled):not(.disabled).active,
  .show > &.dropdown-toggle {
    color: color-yiq($active-background);
    background-color: $active-background;
    @if $enable-gradients {
      background-image: none; // Remove the gradient for the pressed/active state
    }
    border-color: $active-border;

    &:focus {
      @if $enable-shadows and $btn-active-box-shadow != none {
        @include box-shadow($btn-active-box-shadow, 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5));
      } @else {
        // Avoid using mixin so we can pass custom focus shadow properly
        box-shadow: 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5);
      }
    }
  }
}