SASS 基础之十个常见的 Mixins

发布于 2021-12-19 00:15:45 字数 16533 浏览 1223 评论 0

自从开始学习SASS之后,我喜欢上了 SASS。因为他能让我的工作效率更快,同时让我更加节约出时间去做一些我自己喜欢的事情。

现在开始我开始使用 SASS 私下用在我喜欢的项目中,让我更加的对 SASS 喜欢与执着。在使用过程中,SASS 中的 Mixins 让我觉得他的功能强大,使用方便——SASS 的 Mixins 可以一次性定义功能模块,让你在任何地方调用,并且可以无限制的重用。

Compass 是一个 SASS 的 mixins 库,里面包括了很多有用的功能模块,比如说 border-radiusbox-shadow 等。但很多时候,这些功能模块还无法满足我们所有项目的需求,但是大家可以根据自己的需求定义一些功能模块。接下来主要和大家一起探讨一些在实际项目中经常使用的 mixins

声明 Mixins

Mixins是SASS中的一个强大的功能。使用@mixin根据功能定义一个模块,然后在需要使用的地方通过@include来调用声明的mixins。其主要功能是可以让你的代码简洁高效。如果你在你的开发工作中使用了SASS,毫无疑问你正在使用一些mixin

常用的 Mixins

经过前面的学习(或者你使用SASS很久)之后,我想对于SASS的mixins并不会太陌生,甚至说,你有使用SASS做过项目的经验的话,你肯定有写过不放有用的mixins,并且准备用于你手中的任何项目中,但对于一个初学SASS的初学者(像偶一样的),对于怎么定义一些常用的mixins还是略有难度的。接下来,我在网上参考了不少实例,整理了一些自认为常用而用功能强大的mixins,希望这些mixins对于初学者对SASS有一个更理性的认知,当然更希望大家能通过这里的一些mixins获得更好的灵感,制作出更有意义的mixins

inline-block

inline-block在CSS中经常会有碰到,比如说我们需要制作一个水平排列的表单,其中 label标签需要和表单控件(比如说input[type="text"]、input[type="checkbox"]等)垂直居中对齐,我们常用的就是给他们加上下面的样式:

label,
input {
  display: inline-block;
  vertical-align: middle;
  *display:inline;
  *zoom: 1;
  *vertical-align: auto;
}

在SASS中,我们可以定义一个inline-block()

$inline-block-alignment: middle !default;//设置一个默认的对齐方式

// 提供一个跨浏览器的方法来实现`display:inline-block`
@mixin inline-block($alignment: $inline-block-alignment) {
  display: inline-block;
  @if $alignment and $alignment != none {
  vertical-align: $alignment;
  }
  @if $legacy-support-for-ie {
  *vertical-align: auto;
  zoom: 1;
  *display: inline;
  }
}

在这个inline-blockmixin中,定义了一个参数$alignment,并且给其传了一个参数$inline-block-alignment

当设置$inline-block-alignmentnone或者false时,inline-block的Mixins中禁止输出vertical-align的属性值;当然我们可以通过设置$alignment的值来修改vertical-align的默认值。

众所周知,display:inline-block在IE低版本的浏览器中存在一定的问题,如果我们需要实现一个兼容IE低版本的inline-block效果,我们就得考虑在这个mixin中设置一个开关,当我需要兼容的时候开启,否则我就关闭。出天这个原因,我们在这个mixins中使用:

@if $legacy-support-for-ie {
  *display: inline;
  zoom: 1;
  *vertical-align: auto;
}

注:这里的*vertical-align:auto并不是用来处理兼容inline-block所需的代码,而是用来兼容vertical-align属性的。

inline-blockmixin定义好了,或许大家会关心如何调用,这个很简单,我们来看一个简单的例子:

//SCSS

$legacy-support-for-ie: true !default;

label,
input {
  @include inline-block();
}

//CSS

label,
input {
  display: inline-block;
  vertical-align: middle;
  *vertical-align: auto;
  zoom: 1;
  *display: inline; 
}

这里我们就只是简单的通过@include调用了刚才声明的inline-block。这个时候你可能会想,我已经不理IE很久了,而且我也不想输出vertical-align。实际上这些并不是难度,刚才我们在定义inline-block也说明了,只要$inline-block-alignment值为none或者flase就不会输出。至于在IE下不输出兼容代码,那就更简单的了,只需要设置$legacy-support-for-iefalse就OK了,如:

//SCSS

$legacy-support-for-ie: false !default;

label,
input {
  @include inline-block(none);
}

//CSS

label,
input {
  display: inline-block; 
}

此时如果你想让元素顶部对奇,那也不是一件难事:

//SCSS

$legacy-support-for-ie: false !default;

label,
input {
  @include inline-block(top);
}

//CSS

label,
input {
  display: inline-block;
  vertical-align: top; 
}

水平居中

元素水平居中实现方法很多种,但我们最常用的还是给一个元素设置一个具体的宽度(设置min-widthmax-width也行,但在IE下需要另行考虑),配合 margin-leftmargin-right 的值为auto实现水平居中:

@mixin horizontal-center {
  margin-left: auto;
  margin-right: auto;
}

这个时候,只需要在有宽度的元素中调用horizontal-center,就能让一个元素实现水平居中:

//SCSS

$width: 960px !default;
.container {
  width: $width;
  @include horizontal-center;
}

//CSS

.container {
  width: 960px;
  margin-left: auto;
  margin-right: auto; 
}

这个horizontal-center没有设置任何参数,通过前面的基础知识,我们可以得知mixin只会复制代码,并不会进行代码合并,为了让样式中相同代码合并,我们可以通过%placeholders来实现。换句话说,在定义的horizontal-center基础上,我们可以配合%来进行二次声明:

%horizontal-center {
  @include horizontal-center;
}

接下来可以通过@extend来配合使用:

//SCSS

$width: 960px !default;
.container {
  width: $width;
  @extend %horizontal-center;
}

//CSS

.container {
  margin-left: auto;
  margin-right: auto; 
}

.container {
  width: 960px; 
}

%horizontal-center@mixin horizontal-center所起的功能是一样的,都是用来实现元素水平居中,其最大的区别是,前者适合使用在多个元素之上,后者适合使用在单个元素之上。这样说或许有点迷糊,我们来举个栗子:

假设在样式中,我有.container.menu两个元素,他们宽度不一致,但都希望实现水平居中,那么这个时候我们就可以使用%horizontal-center,因为这样,我们可以将居中这部分代码合并在一起:

//SCSS

$width: 960px !default;
.container {
  width: $width;
  @extend %horizontal-center;
}

.menu {
  width: $width / 2;
  @extend %horizontal-center;
}

//CSS

.container, .menu {
  margin-left: auto;
  margin-right: auto; 
}

.container {
  width: 960px; 
}

.menu {
  width: 480px; 
}

从编译出来的CSS代码中很明显的可以发现:.container.menu有关于居中代码合并在一起:

.container, .menu {
  margin-left: auto;
  margin-right: auto; 
}

对于@mixin horizontal-center比较适合在一个元素实现水平居中的时候使用。如果在样式之中仅有一个元素要水平居中,也使用%horizontal-center的话,会让你失望的:

//SCSS

$width: 960px !default;
.container {
  width: $width;
  @extend %horizontal-center;
}


//CSS
.container {
  margin-left: auto;
  margin-right: auto; 
}

.container {
  width: 960px; 
}

从实例中明显的可以看出,原本在.container中一次性能完成的事情,但使用%horizontal-center却将样式拆分成两个部分。这种并不是大家想要的,或者说希望看到的。出于这个情况之下,我们还是使用@mixin horizontal-center会完美一些:

//SCSS

$width: 960px !default;
.container {
  width: $width;
  @include horizontal-center;
}


//CSS

.container {
  width: 960px;
  margin-left: auto;
  margin-right: auto; 
}

浮动与重置浮动

在CSS中,浮动常用来实现布局效果,当然很多时候也使用浮动来完成文字围绕图片的效果。常见的就是左浮动、右浮动。虽然浮动功能强大,能帮助我们实现很多布局效果,但有时候在相同的模块中,要将浮动重置掉,不得不把当前设置的浮动效果,使用none重置。对于浮动的出现频繁率,将浮动和重置浮动列入SASS的mixins

首先我们通过@mixin来声明一个float

@mixin float($side:left){
  float: unquote($side);
  @if $legacy-support-for-ie {
    _display:inline;
  }
}

由于IE6下浮动碰到同方向的margin会引起双倍margin的Bug,为了解决这个Bug,在@mixin float中添加一个条件判断,如果支持IE6,就添加:

@if $legacy-support-for-ie {
  _display:inline;
}

对于float我们只需要声明这个就能使用了,但为了让你的代码更具语义化,可以在此基础上增加一个pull-left为左浮动和pull-right为右浮动:

//左浮动

@mixin pull-left{
  @include float(left);
}

%pull-left {
  @include float(left);
}


//右浮动

@mixin pull-right{
  @include float(right);
}

%pull-right {
  @include float(right);
}

如此一来,我们可以轻松的通过@include或者@extend来调用定义好的pull-left或者pull-right

//SCSS

.col{
  @extend %pull-left;
}

.aside {
  @include pull-right;
}

//CSS
.col {
  float: left;
  _display: inline; 
}
.aside {
  float: right;
  _display: inline; 
}

浮动让你既爱又恨,在实际需求之中难免需要重置掉已设置的了浮动的功能,并且重置display。那么接下来定义的reset-float就可以轻松帮你完成你要的功能:

@mixin reset-float($display:block){
  float: none;
  display: $display;
}

此处传了一个参数$displayreset-float。他可以帮你在重置float的时候,重置display属性,默认情况下,@include reset-float出来display:block,但你可以显式的传一个值给他,从而重置display属性:

//SCSS

.content {
  @include reset-float(inline);
}

//CSS
.content {
  float: none;
  display: inline; 
}

清除浮动 clearfix

有浮动就有清除浮动,在这里主要来看最常用的 clearfix 清除浮动方法。同样先创建一个 clearfix:

@mixin clearfix {
  @if $legacy-support-for-ie {
    *zoom: 1;
  }
  &:before,
  &:after {
    content: "";
    display: table;
  }
  &:after {
    clear: both;
    overflow: hidden;
  }
}

%clearfix {
  @include clearfix;
}

同样为了兼容IE低版本浏览器,里面添加了@if $legacy-support-for-ie开关,如果其值为true就开启,如果其值为false就关闭,这个和前面介绍的是一样功能。

创建好clearfix后,直接在你需要的地方通过@extend@include方法调用(对于他们的区别,此处不在阐述):

//SCSS
.container {
  @extend %clearfix;
}

//CSS
.container {
  *zoom: 1; 
}
.container:before, 
.container:after {
  content: "";
  display: table; 
}
.container:after {
  clear: both;
  overflow: hidden; 
}

图片替代文本

图片替代文本,这是页面中常用的效果,平时解决方法,就是在需要使用图片替代文本的地方,添加一个类名。这种方法虽然能解决问题,但维护真心的蛋疼,小生深有感受呀。然而我们在SASS的Mixin中定义一个 ir(Image replacement),将功能都写成一个模块,需要的时候调用,省得不停的添加和删除类名。

十多种图片替换文本的方法,找了最新发现的一种(来自于H5bp):

@mixin ir {
  background-color: transparent;
  border: 0;
  overflow: hidden;
  @if $legacy-support-for-ie {
    *text-indent: -150%;
  }

  &:before {
    content: "";
    display: block;
    width: 0;
    height: 150%;
  }
}

%ir {
  @include ir;
}

这是来自于H5bp中的一种图片替换文本方法,但没有测试ie低版本,现代浏览测试是OK的,如果大家觉得这种方法对兼容性不可靠,可以换过一些常用的,可靠的版本。

在实际使用中要让图片替换文本成功,我们还需要在对应的地方加入一些基本的样式。或许你会问,为什么不一起加入呢?因为针对不同的元素,在这里统一加,有点浪费,所以使用时可以根据元素自身进行加载:

//SCSS

#logo {
  display: block;
  width: 100px;
  height: 100px;
  @include ir;
}

//CSS
#logo {
  display: block;
  width: 100px;
  height: 100px;
  background-color: transparent;
  border: 0;
  overflow: hidden;
  *text-indent: -150%; 
}
#logo:before {
  content: "";
  display: block;
  width: 0;
  height: 150%; 
}

隐藏元素

最常用来隐藏一个元素的方法是使用display:none,可这并不是一个完美的方法,这样会让屏幕阅读器无法读到这个元素。为了解决这个问题,使用另外一种方法来实现元素的隐藏,而这种方法仅在浏览器中隐藏了元素,而屏幕阅读器却能读到这个元素。

//1.浏览器和屏幕阅读器都隐藏元素

@mixin hidden {
  display: none !important;
  visibility: hidden;
}

%hidden {
  @include hidden;
}

//2.仅浏览器隐藏,屏幕阅读器不被隐藏

@mixin visuallyhidden {
  @if $legacy-support-for-ie {
    clip: rect(0,0,0,0);
  }
  border: 0;
  clip: rect(0 0 0 0);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  width: 1px;

  ////扩展了`.visuallyhidden`,充许`.focusable`元素通过键盘获取
  &.focusable:active,
  &.focusable:focus {
    clip: auto;
    height: auto;
    margin: 0;
    overflow: visible;
    position: static;
    width: auto;
  }
}

%visuallyhidden {
  @include visuallyhidden;
}

//3.隐藏元素,但布局中占有空间

@mixin invisible {
  visibility: hidden;
}

%invisible {
  @include invisible;
}

截取文本 text-overflow

截取文本,到目前为止对于单行文本,我们可以使用text-overflow来实现。但对于多行文本的截取,使用纯CSS来实现,还是很蛋疼的。Roman在《CSS Ellipsis: How to Manage Multi-Line Ellipsis in Pure CSS》一文中详细介绍了使用纯CSS实现多行文本截取的方法。不过,在此处我们不做过多的深入,因为这里所说的文本截取是针对于单行文本。

对于单行文本的截取,需要同时满足三个条件:明确的宽度文本强制不换行隐藏多余文本。只有在这三个条件都成立的情况这下,配合text-overflow属性才能截取文本,并用代替截取不显示的文本。

知道实现的方法,定义mixin就简单多了:

@mixin singleline-ellipsis($substract:0){//`$substract`单位为%
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 100% - $substract;
}

%singleline-ellipsis {
  @include singleline-ellipsis;
}

同样定义了mixin%placeholders,但这个singleline-ellipsis和前面的使用略有不同。主要区别在于,@mixin singleline-ellipsis可以给其传一个参数$substract,从而改变元素的width值,而%singleline-ellipsis是无法给其传值,元素的宽度永远为100%:

//SCSS

.text-overflow {
  @extend %singleline-ellipsis; 
}

.text-overflow2 {
  @include singleline-ellipsis(); 
}

.text-overflow3 {
  @include singleline-ellipsis(20); 
}

//CSS
.text-overflow {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 100%; 
}
.text-overflow2 {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 100%; 
}

.text-overflow3 {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 80%; 
}

透明度 opacity

opacity属性主要是用来设置元素的透明度,不过他会让元素的所有后代元素继续这个透明度,直接影响了可视度。但有时候我们还真缺不了这个东东,不过本人更建议使用RGBA来处理元素的透明度,只可以IE低版本会让你受尽折磨。为了让你减轻兼容的痛,还是先来看看opacitymixin如何定制吧。

@mixin opacity($opacity:50) {
  opacity: $opacity / 100;
  @if $filter{
  filter: alpha(opacity=$opacity);
  }
}

这里需要注意,为了判断是否兼容IE低版本,此处设置了一个开关变量$filter,如果其值为true就兼容,如果其值为false就不兼容。并且这个开关变量$filter和前面设置的$legacy-support-for-ie开关,都放置在同一个文件_setting.scss中。当然如果你不做统一规划,你只需要在将其声明就可以。

在实际应用就很简单的了:

//SCSS

.opacity {
  @include opacity(65);
}

//CSS
.opacity {
  opacity: 0.65;
  filter: alpha(opacity=65); 
}

禁用样式 disabled

禁用样式一般都出现在表单中,比如说某个输入框input[type=text]或者某个按钮input[type=button]设置了disabled="disabled"属性,让用户无法操作。为了能让用户知道这些控制无法操作,所以特意给他定义一个.disabled样式,用户一看就知道这些控件不能操作。


@mixin disabled($bgColor: #e6e6e6,$textColor:#ababab){
  background-color: $bgColor !important;
  color: $textColor !important;
  cursor: not-allowed !important;
}

这里设置了两个参数,第一个是$bgColor用来定义背景色,第二个是$textColor用来定义文本色。同时为他们设置了默认值,不过在实际调用时,可以根据自己需要修改颜色:

//SCSS
input[disabled]{
  @include disabled(#efefef,#ccc);
}

//CSS
input[disabled] {
  background-color: #efefef !important;
  color: #cccccc !important;
  cursor: not-allowed !important; 
}

最小高度 min-height

min-height最小高度,主要用来设置元素的最小高度。当元素内容撑不到所需高度时,就可以使用min-height轻松实现。

@mixin min-height($height){
  min-height: $height;
  height: auto !important;
  @if $legacy-support-for-ie {
    _height: $height;
  }
}

当你要给一个元素设置min-height100px时,只需要这样使用:

//SCSS
.min-height {
  @include min-height(100px);
}

//CSS
.min-height {
  min-height: 100px;
  height: auto !important;
  _height: 100px; 
}

在这篇文章中,根据 sassCore 中的 mixin.scssCompassMixins 为依据和参考对像,总结了十个常见的 Mixins,主要包括:设置行内块inline-block、水平居中 horizontal-center、设置浮动 float、重置浮动 reset-float、图片替换文本 ir 等。当然优秀的 Mixins 不只这十个。我只想用这些简单的 Mixins 让大家对SASS更有兴趣。当然还是以学会SASS为出发点。接下来我还会继续为大家介绍其他 Mixins 的定义与使用。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

浮生未歇

暂无简介

文章
评论
18381 人气
更多

推荐作者

夢野间

文章 0 评论 0

doggiejohn

文章 0 评论 0

就此别过

文章 0 评论 0

初见终念

文章 0 评论 0

qq_rvKjBH

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文