首页 > 其他分享 >CSS 也能实现 if 判断?实现动态高度下的不同样式展现

CSS 也能实现 if 判断?实现动态高度下的不同样式展现

时间:2023-11-14 10:47:36浏览次数:41  
标签:容器 container 实现 100% 高度 样式 calc CSS 200px

最近在群里,有个小伙伴问了这么一道很有趣的问题:

  1. CSS 能否实现,容器再某个高度下是某种表现,一旦超出某个高度,则额外展示另外一些内容

为了简化实际效果,我们看这么一张示意效果图:

可以看到,当容器高度没有超过某一个值时,没有箭头图标。反之,箭头图标出现。

这个效果在很多场景都会出现,可以算是一个高频场景,那么在今天,我们能否不使用 JavaScript,仅仅凭借 CSS 实现类似于这样的功能呢?

答案当然是可以,XBoxYan 大佬在 CSS 实现超过固定高度后出现展开折叠按钮 介绍了一种非常巧妙的借助浮动的解法,十分有意思,感兴趣的同学可以先行一步了解。

当然,浮动 float 在现如今的 CSS 世界,运用的已经非常少了。那么除了浮动,还有没有其它有意思的解法?本文我们将一起来探究探究。

方法一:借助最新的容器查询

第一种方法,非常简单,但是对兼容性有所要求。那就是使用容器查询 -- @container 语法。

容器查询在 新时代布局新特性 -- 容器查询 也详细介绍过。

简单而言,容器查询它给予了 CSS,在不改变浏览器视口宽度的前提下,只是根据容器的宽度或者高度变化,对布局做调整的能力。

基于这个场景,我们假设我们有如下的 HTML/CSS 结构:

<div class="g-container">
    <div class="g-content">
        Lorem ipsum dolor s...
    </div>
</div>
.g-container {
    position: relative;
    width: 300px;
    height: 300px;
    resize: vertical;
    overflow: hidden;

    .g-content {
        height: 100%;
    }

    .g-content::before {
        content: "↑";
        position: absolute;
        bottom: 0px;
        left: 50%;
        transform: translate(-50%, 0);
    }
}

它是这么一个样式效果:

其中,我们给元素 .g-content 添加了 resize: vertical,让它变成了一个可以在竖直方向上通过拖动改变高度的容器,以模拟容器在不同内容的场景下,高度不一致的问题:

我们通过元素的伪元素实现了箭头 ICON,并且它是一直显示在容器内的。

下面,我们通过简单的几句容器查询代码,就可以实现让箭头 ICON,只在容器高度超过特定高度的时候才出现:

.g-container {
    container-type: size;
    container-name: container;
}

@container container (height <= 260px) {
    .g-content::before {
        opacity: 0;
    }
}

简单解释一下:

  1. .g-container 它被用作容器查询的目标容器
    • container-type 属性指定了容器的类型为 size,表示我们将使用容器的尺寸来应用样式。
    • container-name 属性指定了容器的名称为 container,以便在后面的容器查询规则中引用。
  2. @container container (height <= 260px) {} 表示这是一个容器查询规则,在括号中的条件 (height <= 260px) 表示当容器的高度小于等于 260px 时,应用该规则下的样式
  3. 具体规则为,如果容器的高度小于等于 260px 时,.g-content 元素的伪元素将变得透明

这样,我们就非常简单的实现了容器在不同高度下,ICON 元素的显示隐藏切换:

完整的代码,你可以戳这里:CodePen Demo -- flexible content

当然,这个方案的唯一缺点在于,截止至今天(2023-11-11),兼容性不是那么好:

那,有没有兼容性更好的方案?当然,来我们一起来看看 clamp + calc 的方案。

方法二:clamp + calc 大显神威

上面效果的核心在于:

  1. 如果容器的高度大于某个值,显示样式 A
  2. 如果容器的高度小于等于某个值,显示样式 B

那么想想看,如果拿容器的高度减去一个固定的高度值,会发生什么?假设一下,ICON 元素的 CSS 代码如下:

.g-content::before {
    content: "↑";
    position: absolute;
    left: 50%;
    transform: translate(-50%, 0);
    bottom: calc(100% - 200px);
}

仔细观察 bottom: calc(100% - 200px),在元素的 bottom 属性中,100% 表示的是容器当前的高度,因此 calc(100% - 200px) 的含义就代表,容器当前高度减去一个固定高度 200px。因此:

  1. 当容器高度大于 200pxcalc(100% - 200px) 表示的是一个正值
  2. 当容器高度小于 200pxcalc(100% - 200px) 表示的是一个负值
  3. 当容器高度等于 200pxcalc(100% - 200px) 表示 0

我们看看这种情况下,整个 ICON 的表现是如何的:

可以看到,当容器高度大于 200px 的时候,箭头 ICON 确实出现了,但是,它无法一直定位在整个容器的最下方

有什么办法让它在出现后,一直定位在容器的最下方吗?

别忘了,CSS 中,还有几个非常有意思的数学函数:min()max()clamp(),它们可以有效限定动态值在某个范围之内!

不太了解的,可以看看这篇 现代 CSS 解决方案:CSS 数学函数

利用 clamp(),我们可以限定计算值的最大最小范围,在这个场景下,我们可以限制 bottom 的最大值为 10px

.g-content::before {
    // ...
    bottom: clamp(-99999px, calc(100% - 200px), 10px);
}

上面的代码 clamp(-99999px, calc(100% - 200px), 10px),核心在于,如果 calc(100% - 200px) 的计算值大于 10px,它只会取值为 10px,利用这个技巧,我们可以在容器高度超长时,把箭头 ICON 牢牢钉在容器的下方,无论容器的高度是多少:

到此,结束了吗?显然没有。

虽然上面的代码,解决当 calc(100% - 200px) 的计算值大于 10px 的场景,但是没有解决,当 calc(100% - 200px) 的计算值处于 -10px ~ 10px 这个范围内的问题。

我们可以清楚的看到,当我们往下拖动容器变高的时候,箭头元素是逐渐慢慢向上出现,而不是突然在某一个高度下,直接出现,所以在实际使用中,会出现这种 ICON 只出现了一半的尴尬场景:

但是,莫慌!这个问题也好解决,我们只需要给 calc(100% - 200px) 的计算值,乘上一个超级大的倍数即可。原因在于:

  1. calc(100% - 200px) 的计算值是负数时,我们其实不希望 ICON 出现,此时,乘上一个超级大的倍数,依然是负数,不影响效果
  2. calc(100% - 200px) 的计算值是正数时,为了避免 ICON 处在只漏出部分的尴尬场景,通过乘上一个超级大的倍数,让整个计算值变得非常大,但是由于又有 clamp() 最大值的限制,无论计算值多大,都只会取 10px

看看代码,此时,整个 bottom 的取值就改造成了:

.g-content::before {
    // ...
    bottom: clamp(-9999px, calc(calc(100% - 200px) * 100000), 10px);
}

通过,将 calc(100% - 200px) 的值,乘上一个超大的倍数 100000,无论是正值还是负值,我们把计算值放大了 100000 倍。这样,整个效果就达成了我们想要的效果:

仔细看上图,ICON 元素从渐现,变成了瞬间出现!与上面的 @container 效果几乎一致,最终达成了我们想要的效果。

其核心就在于 clamp(-9999px, calc(calc(100% - 200px) * 100000), 10px),一定需要好好理解这一段代码背后的逻辑。

基于此,我们就巧妙的利用 clamp() + calc() 方法,近似的实现了类似于 if/else 的逻辑,实在是妙不可言!

CodePen Demo -- flexible content

最后

好了,本文到此结束,希望本文对你有所帮助

标签:容器,container,实现,100%,高度,样式,calc,CSS,200px
From: https://www.cnblogs.com/coco1s/p/17831064.html

相关文章

  • 单例模式C++实现
    单例模式全局静态变量实现饿汉式单例模式饿汉式实现方式是线程安全的。黑#includeusingnamespacestd;/*饿汉式单例模式*/classSingleObject{private:staticSingleObjectinstance;SingleObject(){std::cout<<"Singleton......
  • 软件测试|使用selenium实现文件上传
    简介文件上传是我们web自动化测试工作中经常使用的场景,selenium同样也是支持我们实现自动化的文件上传操作,本文就来给大家介绍一下selenium如何实现自动化文件上传。input标签文件上传一般情况下,文件上传的按钮是一个<input>标签,并且附带的type属性为file,这样的标签我们可以使用sen......
  • js实现大文件分片上传
    简单的实现一个分片上传//设置分片大小(大小根据需求调整)constCHUNK_SIZE=1024*1024;//1MB//选择文件并切割成分片constfileInput=document.getElementById('file-input');constchunks=[];letcurrentChunkIndex=0;fileInput.addEventListener('change',hand......
  • 使用Bert模型实现embedding嵌入
    参考文献:保姆级教程,用PyTorch和BERT进行文本分类-知乎(zhihu.com)模型地址:https://huggingface.co/bert-base-casedfromtransformersimportBertTokenizer,BertModeltokenizer=BertTokenizer.from_pretrained('bert-base-cased')model=BertModel.from_pretrained("......
  • 常用的Linux命令;Linux常用命令用法及实现方式
    1.系统工作命令(1) echo命令:echo命令用于在终端设备上输出字符串或变量提取后的值,语法格式为“echo[字符串][$变量]”。(2) date命令:date命令用于显示或设置系统的时间与日期,语法格式为“date[+指定的格式]”。(3) timedatectl命令:timedatectl命令用于设置系统的时间,英文全称......
  • 图文详解!带你认识 ancert:硬件兼容性标准实现工具!| 龙蜥技术
    编者按:大家都知道OS 其实是硬件设备资源利用的抽象,所以OS和各个硬件设备之间是否兼容,对OS的稳定性是非常关键。今天,龙蜥社区硬件兼容性SIG  Maintainer 吴朝峰为大家介绍龙蜥社区硬件兼容性认证的步骤和流程,以及硬件兼容性认证工具ancert......
  • 实现高效服务器管理的关键技巧和方法是什么?
    高效的服务器管理对于保持系统稳定运行和最大化资源利用至关重要。以下是一些关键技巧和方法:1.自动化管理:自动化工具:使用自动化工具来执行重复性任务,例如自动备份、系统更新和配置管理,以减少手动操作的需求。2.监控和警报系统:实时监控:通过监控软件持续追踪服务器的性能、健康状态......
  • Vue3实现图片滚轮缩放和拖拽
    在项目开发中遇到一个需求:1:用鼠标滚轮可对图片进行缩放处理2:点击按钮可对图片进行缩放处理3:可对图片进行拖拽处理 我在开发中通过自己实现与百度查看优秀的铁子进行了两种类型的使用  <template><divref="imgWrap"class="wrap"@mousewheel.prevent="rollImg"......
  • SQLserver中的递归如何实现
    在SQLServer中,可以使用递归CTE(通用表达式)来实现递归查询。CTE(通用表达式)是一种临时命名结果集,它只存在于查询语句的执行过程中。CTE可以在一个SELECT,INSERT,UPDATE或DELETE语句中使用,并且可以在同一个查询中递归引用自身。这使得递归查询成为可能。下面是一个使用递归CTE的示例:......
  • STM32 HAL 使用串口IDLE中断+DMA实现收发
    STM32HAL使用串口IDLE中断+DMA实现收发cubeMX配置mx配置如下(省去系统时钟,烧录口,工程属性配置)注意:这里关闭ForceDMAchannelsInterrupts然后按下面配置即可(TX和RX的DMA都是normal模式)代码部分uart_com.h:#ifndef__UART_COM_H__#define__UART_COM_H__#include"......