我们都知道,盖房子的时候需要先有设计图,有一个合理的房子框架,然后再开始施工。在前端开发工作中也是一样的,拿到了UI给到的原型设计图,规划好网页的布局往往是最开始需要做的工作。 什么是网页布局网页布局又可以称之为版式布局,它决定了网站的外观风格,是对页面中的文字、图像等进行格式化版式排列。类似于期刊报纸那样,多个板块,多个内容的展示方式。 一个合理的布局,可以让访问者更清晰容易的get到信息的内容重点,对提高用户体验起到很重要的作用。 良好的布局也可以吸引用户对网站的参与度,提升他们在网站页面上停留时间。 网页布局方式关于网页布局方式,有很多种,大致分为以下几种:**静态布局**、**流式布局**、**自适应布局**、**响应式布局**、**弹性布局**等等。对于这几种布局我之前也是傻傻分不清楚,也是查了不少资料。每种布局方式,都是有各自的优缺点和使用场景。* **静态布局**:给页面元素设置固定的宽度和高度,单位用px,当窗口缩小,会出现滚动条,拉动滚动条显示被遮挡内容。针对不同分辨率的手机端,分别写不同的样式文件。* **流式布局**:元素的宽高用百分比做单位,元素宽高按屏幕分辨率调整,布局不发生变化。屏幕尺度跨度过大的情况下,页面不能正常显示。* **自适应布局**:创建多个静态布局,每个静态布局对应一个屏幕分辨率范围,使用@media媒体查询技术。* **响应式布局**:采用自适应布局和流式布局的综合方式,为不同屏幕分辨率范围创建流式布局。* **弹性布局**:要点在于使用ttem和rem单位/tt来定义元素宽度,与流式布局有极大的相似性,但也有不同之处,主要区别在于弹性布局的尺寸主要根据字体大小而变化。 osrc遇到的布局问题 前几天,群里的几个朋友反馈了OSRC社区网站在屏幕不同缩放比例或者不同分辨率下card信息展示的样式问题。图片1: image src='https://oss.osrc.com/wiki/img/1670658192767_1224809086' width=800 height=400 图片2: image src='https://oss.osrc.com/wiki/img/1670658204552_509347765' width=600 height=400 可以看到,出现了字体的重叠或溢出等样式问题。 开发之初,我和小伙伴还真没有发现这个问题,直接的原因是因为我们的电脑屏幕默认就没有进行缩放设置,在100%缩放比例下,card的样式看着还是可以的。其实根本原因还是在开发时没有考虑周全,也是因为对弹性布局的认识还不够。在这里呢,就要特别感谢在OSRC分享交流群里给我们提出这个issue的几位朋友了。OSRC分享交流群汇聚了很多从事开源的朋友,其中也不乏知名开源项目的作者,也是欢迎志同道合的朋友,可以进群进一步[交流](https://www.osrc.com/contact)。下面就总结一下修复这个问题的过程以及在这个修复的过程中,对弹性布局更进一步的认识和对chakra一些组件对弹性布局特性支持的实践。 原因探索查看代码,旧代码在card的`Box`外层,包装了`AspectRatio ratio={xxx}`组件,限制了每个card的宽高比,但是高度和宽度并没有限制,导致在缩放时,card里的元素会跟着变化,但是不满足上述的宽高比。 解决方案1. 可以固定每个card的高度和宽度,这样不管怎么缩放,card也不会变形。2. 去掉`AspectRatio ratio={xxx}`,不限制宽高比,这样card里的元素布局会根据版式自动排列。网页中的card大小会随着网页本身的条件而改变,高度也会因此而改变,避免一些极限情况,可以指定card的最小高度minH做一下限制。 两种方案其实都是可以的,我是采用了第二种方案。因为如果固定宽高的话,那么项目的card、主题的card、应用的card、用户的card等有些可以统一,有些就统一不了,还需要单独处理,稍微麻烦点。 代码改造至于card的版式容器,选择chakra提供的Wrap或者Gird都是可以的。Wrap可以为其包裹的元素设置共同的间距spacing,如果空间不够,元素也会自动换行。Grid就是众所周知的栅格布局了,这里呢我们采用的Grid组件,利用Grid的特性,结合着chakra提供的响应式风格语法,来实现的card列表多端自适应。```typescriptSimpleGrid columns={{ base: cols.base, md: cols.md, xl: cols.xl, '2xl': cols['2xl'] }} maxW={2560} w={'full'} spacing={0} p={px} CardList xxx/ /SimpleGrid```改完一切似乎可以了,各种缩放比例下,card的样式看起来没啥问题,也测试了一会儿。但是新的问题出现了:在部分页面,当鼠标移动到Card上时,页面出现了抖动! 页面抖动优化什么原因呢,hover时页面出现了抖动,那原因肯定就是出在hover身上。页面抖动,其实也就是页面里的元素布局发生了改变。查看下代码:```typescript Box w='full' h='full' minH={minH} transform={scale(1)} transition={0.15s padding ease} padding={hoverEffect && 4} _hover={hoverEffect ? { padding: 2 } : {}} role=group Element / /Box```hover时影响布局的,只可能是Box的padding改变导致的了。那hover时怎么能不改变Box的大小呢,之前的padiing改变,目的就是为了实现一个card放大的效果。所以可以采用`scale`来实现同样的动画效果,并且`scale`不会影响布局。```typescript Box w='full' h='full' minH={minH} padding={hoverEffect && 4} animation='' _hover={hoverEffect && { transform: 'scale(1.030)', transition: '0.15s ease', cursor: 'pointer' }} role=group Element / /Box ```好了,页面抖动的问题解决了,动画效果也实现了。但是这个动画效果有点不自然,当鼠标放在card上时会触发hover伪类添加的动画效果,但是鼠标离开时,hover效果会中断,看起来很生硬。 hover动画效果优化Hover其实是伪类的一种。所谓的伪类,就是指当元素处于某种状态时(滑动、点击等)为其添加对应的样式,这个状态是根据用户行为而动态变化的。分析下原因:当鼠标放在card上时,会触发hover中的transition效果,但在鼠标离开后,hover中的CSS样式瞬间消失,导致动画消失并且样式直接回到无hover状态。知道什么原因导致的,那就也好解决了: 由于非伪类触发状态下的样式会直接应用到触发伪类的状态中,所以可以将transition效果直接写到非hover状态下的样式。hover状态下,只需要书写动画效果即可。 ```ts Box w='full' h='full' minH={minH} padding={hoverEffect && 4} transition={0.15s ease} //动画效果 _hover={hoverEffect && { transform: 'scale(1.030)', // transition: '0.15s ease', 提取到非hover状态下 cursor: 'pointer' }} role=group Element / /Box ```到这里,就完美解决了card的hover效果消失可以平滑过渡到初始状态的动画问题。