SASS 基础之十个常见的 Mixins

发布于 2021-12-19 00:15:45 字数 16533 浏览 1210 评论 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技术交流群

发布评论

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

关于作者

浮生未歇

暂无简介

0 文章
0 评论
18378 人气
更多

推荐作者

1CH1MKgiKxn9p

文章 0 评论 0

ゞ记忆︶ㄣ

文章 0 评论 0

JackDx

文章 0 评论 0

信远

文章 0 评论 0

yaoduoduo1995

文章 0 评论 0

霞映澄塘

文章 0 评论 0

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