关于前端:由-transform-被占用引发的思考🤔

欢送关注我的公众号:前端侦探

聊一聊对于transform的一些事以及简单属性的解决形式

一、transform 很容易被占用

家喻户晓,CSS 中的transform是一个蕴含很多值的属性,例如

div{
  transform: translate(-50%, -50%) scale(1.5)
}

然而,这并不是简写,而是就该这么写,这一点和background不一样

div{
  background: url('1xxx') 10px 10px / 20px 20px no-repeat; 
}
/*等同于以下写法*/
div{
  background-image: url('1xxx'); 
  background-position: 10px 10px;
  background-size: 20px 20px;
  background-repeat: no-repeat;
}

离开写的益处在于,如果只须要扭转某一部分就很容易笼罩

div.div1{
  background-image: url('2xxx'); /*只扭转图片,不扭转其余*/
}

回到后面,如果心愿扭转transform中的某一部分,就不太行了,必须把没扭转的局部也写一遍,而且更改的局部也无奈抽离进去作为一个公共的款式

div.scale{
  transform: scale(2) /*这样不行,会失落translate*/
}
/*必须写残缺*/
div.scale{
  transform: translate(-50%, -50%) scale(2)
}

那如何奇妙的躲避这个问题呢?

二、目前的几种思路

1. 用其余形式来代替 transform

碰到这种状况,第一感觉可能就是放弃原有transform属性,用其余形式代替。

比方translate(-50%, -50%)个别是为了实现元素居中成果,能够用flex等其余形式实现

.parent{
  display: flex
}
div{
  margin: auto; /*通过margin:auto实现居中*/
}

再比方translate(10px, 10px)这样的偏移,能够用left或者margin-left等形式实现,、

div{
  position: relative;
  left: 10px;
  top: 10px;
}

或者罗唆再包裹一层父级,也能防止transform被占用的问题。

<div class="wrap">
  <div class="box">
    
  </div>
</div>

不过,这些形式都是躲避形式,其实还有官网解决方案

2. transform 的独自赋值

后面提到过transform并不是一个简写属性,所以没有方法像background那样对某一部分进行赋值。为了解决这个问题,从Chrome 104开始,浏览器终于正式反对独自赋值了

有趣味的能够参考这篇文章:解放生产力!transform 反对独自赋值扭转

就拿后面那个例子来说

div{
  transform: translate(-50%, -50%) scale(1.5)
}

能够写成

div{
  translate: -50% -50%;
  scale: 1.5
}

这样如果须要扭转某一部分,就只须要像一般属性一样笼罩就行了

div.scale{
  scale: 2
}

不过目前兼容性欠佳,审慎应用!(适宜外部我的项目尝鲜)

三、借助 CSS 变量拆分属性

后面的transform 的独自赋值尽管很好,然而太新了,无奈立即在我的项目中应用。上面介绍一个兼容性更好,应用更释怀的解决方案。

还是下面这个例子

div{
  transform: translate(-50%, -50%) scale(1.5)
}

通过 CSS 变量,将transform拆分

div{
  --translate: -50%, -50%;
  --scale: 1.5;
  transform: translate(var(--translate)) scale(var(--scale))
}

通过这样拆分当前,CSS 变量就成了独立属性,如果须要笼罩,只须要批改其中一个就行了,而无需关注--translate是什么样的,这样变动的局部就能够独自作为一个公共的款式了,如下

.div1{
  --translate: -50%, -50%;
}
.div1{
  --translate: 10px, 10px;
}
div.scale{
  --scale: 2; /*无需关注其余transform,能够作为公共的款式*/
}

是不是十分清晰明了?上面是一个演示demo

[type="checkbox"]:checked+div{
  --scale: 1.5
}

成果如下

残缺代码能够查看以下任意链接:

  • CSS transform (codepen.io)
  • CSS transform – 码上掘金 (juejin.cn)
  • CSS transform (runjs.work)

四、借助 @property 实现过渡动画

下面的实现看似完满,其实还是有问题的,比方加一个动画。

因为拆分成了 CSS 变量写法,所以动画的变动对象也变成了 CSS 自定义属性(--scale),如下

div{
  /**/
  animation: scale 1s infinite linear alternate;
}
@keyframes scale {
  from {
    --scale:1
  }
  to {
    --scale:1.5
  }
}

实际效果是这样的

动是动了,然而没有过渡,太僵硬了,那如何解决呢?

这就须要用到@property了,是干什么的呢?简略来讲,能够自定义属性,让自定义变量像色彩一样进行过渡和动画,换句话说,当初执行动画的是--scale这个属性,而不再是transform

对于@property的利用,还能够参考这几篇文章:

  • 还在应用定时器吗?CSS 也能实现电子时钟
  • 自定义计数器小技巧!CSS 实现长按点赞累积动画
  • 动画合成小技巧!CSS 实现动感的倒计时成果
  • 如何让CSS计数器反对小数的动态变化?

所以,要实现过渡动画,只须要将这个自定义属性通过@property定义一下就行了,如下

@property --scale { 
  syntax: '<number>';
  inherits: false;
  initial-value: 1;
}

成果如下

和传统实现成果一样,然而代码上更加优雅

残缺代码能够查看以下任意链接:

  • CSS transform @property (codepen.io)
  • CSS transform @property – 码上掘金 (juejin.cn)
  • CSS transform @property (runjs.work)

五、不仅仅是 transform

上面来拓展一下,关上你的格局。

除了transform,还有很多其余简单的 CSS 属性,在现阶段并没有离开的状况下,这种通过 CSS 变量的形式就再适宜不过了,比方filter

el{
  filter: brightness(0.4) invert(75%) grayscale(50%);
}

通过 CSS 变量拆散开来就是

el{
  --brightness: 0.4;
  --invert: 75%;
  --grayscale: 50%;
  filter: brightness(0.4) invert(75%) grayscale(50%);
}

这样在做一些图片调整时,能够间接用独自的变量管制了,比方像keynote这样的

再比方rgb色彩值,写成一个变量不好管制,拆分成三个变量就容易多了

el{
  --r: 255;
  --g: 255;
  --b: 255;
  color: rgb(var(--r), var(--g), var(--b));
}

这样在做一些色彩调整交互时就十分不便,还是keynote中的例子

还有一些能够有限叠加的属性,比方background-image,对,又是这个,堪称是相当简单了,在有多层背景,而且背景都是很长一段base64时,就成了这样

el{
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E %3Cpath d='M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm-32-316v116h-67c-10.7 0-16 12.9-8.5 20.5l99 99c4.7 4.7 12.3 4.7 17 0l99-99c7.6-7.6 2.2-20.5-8.5-20.5h-67V140c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12z'%3E%3C/path%3E %3C/svg%3E"), url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E %3Cpath d='M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm-32-316v116h-67c-10.7 0-16 12.9-8.5 20.5l99 99c4.7 4.7 12.3 4.7 17 0l99-99c7.6-7.6 2.2-20.5-8.5-20.5h-67V140c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12z'%3E%3C/path%3E %3C/svg%3E"), url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E %3Cpath d='M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm-32-316v116h-67c-10.7 0-16 12.9-8.5 20.5l99 99c4.7 4.7 12.3 4.7 17 0l99-99c7.6-7.6 2.2-20.5-8.5-20.5h-67V140c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12z'%3E%3C/path%3E %3C/svg%3E")
}

这样一段 CSS 就像乱码一样,十分不利于浏览,分不清哪个图片是哪个,像这种状况就能够借助 CSS 变量改写成如下模式

:root{
  --背景1:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E %3Cpath d='M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm-32-316v116h-67c-10.7 0-16 12.9-8.5 20.5l99 99c4.7 4.7 12.3 4.7 17 0l99-99c7.6-7.6 2.2-20.5-8.5-20.5h-67V140c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12z'%3E%3C/path%3E %3C/svg%3E");
  --背景2:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E %3Cpath d='M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm-32-316v116h-67c-10.7 0-16 12.9-8.5 20.5l99 99c4.7 4.7 12.3 4.7 17 0l99-99c7.6-7.6 2.2-20.5-8.5-20.5h-67V140c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12z'%3E%3C/path%3E %3C/svg%3E");
    --背景3:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E %3Cpath d='M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm-32-316v116h-67c-10.7 0-16 12.9-8.5 20.5l99 99c4.7 4.7 12.3 4.7 17 0l99-99c7.6-7.6 2.2-20.5-8.5-20.5h-67V140c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12z'%3E%3C/path%3E %3C/svg%3E");
}
el{
  background-image: var(--背景1), var(--背景2), var(--背景3)
}

这样对于el来说,用到了哪些背景是不是高深莫测呢?

六、总结一下

以上就是本文全部内容了,也是 CSS 变量的一些实战小技巧,上面总结一下

  1. 局部 CSS 属性比较复杂,比方transform,很容易被占用
  2. 通常的解决形式是躲避,比方换一种居中形式,或者用lefttop等代替
  3. 新呈现的transform 的独自属性能够解决这个问题,目前还比拟新,仅适宜外部我的项目尝鲜
  4. 借助 CSS 变量能够拆分简单的属性
  5. 借助 @property 让CSS自定义属性反对过渡动画
  6. 不仅仅是 transform,思维放开,简单的属性都能够采取这样的思路

最初,如果感觉还不错,对你有帮忙的话,欢送点赞、珍藏、转发❤❤❤

欢送关注我的公众号:前端侦探

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理