现代 UI 布局的基础逻辑是什么?

2021-09-01 12:14:42 +08:00
 RecursiveG

作为一个长期写后端代码的程序员,偶尔需要糊一个 GUI,就会不可避免的陷入“纸笔草稿一分钟,布局调试一整天”的情况。刚入门写 VB6 的时候只要四个值:左边距离 /顶部距离 /长 /宽。虽然不够灵活但至少“所写即所得”。

但是现代布局似乎更喜欢用各种 layout/constraint/margin 之类,对于我来说除了实际运行一下根本想不出每个元素会被放在哪里,也看不出究竟是谁决定了谁的哪个属性。比如说 CSS 里的长度单位可以是100%,这看起来像是在说“先决定外层元素大小,再决定内部元素大小”,但是 CSS 又允许内层元素撑大外层元素,意味着需要先决定内层内部元素大小再决定外层元素大小。

类似的还有比如“外层容器最大大小小于内层容器最小大小,溢出怎么办”或者是“外层容器最小大小大于内层容器最大大小,空白怎么办”。

这看上去就像是一坨橡皮筋把所有的控件连在一起,然后指望松手以后能得到那个想要的形状,然后大部分时候只能得到一团浆糊。

各位的脑内布局引擎都是怎么工作的?

2041 次点击
所在节点    前端开发
13 条回复
cmdOptionKana
2021-09-01 12:22:07 +08:00
桌面软件可以用固定位置和固定大小,但现代网页 UI 不得不考虑适应不同尺寸的屏幕。

你说的问题,是 UI 设计的天然复杂度,很多人吐槽 CSS 难学,其实根本原因是天然复杂度就很高。

因此,如果不是专业搞 UI,只是偶尔弄一下的话,找个 UI 框架就行了,这个框架会提供几个布局的“套路”,学套路很容易,拿来就用,复杂性都已经被封装起来了。

如果对细节感兴趣,就从基础慢慢学,只要有兴趣学起来也不难。
nicevar
2021-09-01 12:45:44 +08:00
vb6 时代的软件简单粗暴,不存在什么适配一说,很多软件上来就写死窗口大小,禁止窗口拉伸,不像现在的软件要适应各种屏幕,还要考虑 PC 和移动端。
移动端基本上所有的系统 UI 框架我都用过,早期人手一套框架的年代,都是弱化版的 web 那一套,发展到后期主要都是 AutoLayout 一类的方案,目前我觉得 Android 的 ConstraintLayout 用起来是最舒服的。
luob
2021-09-01 13:12:14 +08:00
css 完全兼容这种写法,position: absolute + left/top/width/height 四个值可以解决任何布局问题。很多东西都是这么写的,比如各种 UI/原型图工具导出的 html

你倒是用啊,可没有人不让你这么写。

------------------------------

现代 UI 布局的逻辑就是所见即所得, 反而只考虑 left/top/width/height 四个值的写法根本就不是所见即所得。

举个例子,你眼前这个帖子的这个容器的位置宽高应该怎么表示,你的脑子里会自动算出宽多少高多少左边距离浏览器 多少上边距离浏览器多少吗?根本不会这样,人脑的思考逻辑是这样的,这个帖子首先宽度等于屏幕宽度,但是也不能无限大下去,最多 770px. 这时屏幕会多出来一部分宽度,可以用 margin-left/right 调整容器的左右位置,或者直接设为 auto,它就会自己居中。

什么是所见即所得,这才是所见即所得。
johnwood
2021-09-01 13:16:49 +08:00
盒子模型+flex
autoxbc
2021-09-01 13:37:52 +08:00
复杂系统仅凭人脑静态分析难以得到最终的运行结果,这是复杂系统的常态,就像后端不是也要调试器来跟踪变量

为什么 CSS 需要在运行中调试就是不可接受的呢,大概还是笃信前端这点东西是低级的,解决的问题并不复杂
wanguorui123
2021-09-01 13:40:15 +08:00
Flex 和 Grid 布局
Sapp
2021-09-01 14:20:31 +08:00
用 flex,简单的一批。你只需要把页面分割成 n 个盒子,盒子宽高你通过 width height 设置,然后 flex 设定盒子内部的盒子的布局,是横向还是竖向,居中还是两边。内部的盒子也重复一下这个逻辑就可以布局了
Jaosn
2021-09-01 17:30:34 +08:00
万物皆可 Flex
KouShuiYu
2021-09-01 18:30:33 +08:00
flex 布局
RecursiveG
2021-09-02 11:13:25 +08:00
楼上不少人在试图解释为什么某种写法(flex/box model/auto etc.)符合直觉,但是符合直觉不一定符合逻辑。比如还是考虑 VB6 的那种写法,你可以从顶层到底层依次计算每个元素的位置和大小,整个流程是一个 Tree,如果有冲突那就在控件内部处理,可以截断也可以加滚动条。再比如 3 楼的那个居中例子,可以理解成先决定外部和内部容器的大小,然后再决定内部容器的位置,那就是一个 DAG 。

如果我没记错 flex(包括其他的布局系统)可以做类似这样的操作:在同一个父元素里的两个子元素同时扩大,直到填满整个父元素。这里就有问题了,你为了知道需要扩张多少,得先知道子元素的大小来算可用空间,但是这时候还没扩张呢,子元素的大小从哪儿来?依赖就有环了。怎么处理?怎么保证收敛而不是发散或者震荡?
RecursiveG
2021-09-02 11:14:49 +08:00
@autoxbc 复杂系统也可以有逻辑,又复杂又没逻辑的东西我一般称之为屎山。
vision1900
2021-09-06 00:59:06 +08:00
你可能不相信,项目里我用 flex 来写 table
laicanwen
2021-09-28 11:34:50 +08:00
@RecursiveG 就像三楼说的,你完全可以用 [绝对定位 + 内外边距 + 定高定宽] 完成你要的写法,只要你的需求可以得到满足,用自己最舒服的写法就可以。GUI 不是你的主业,总结一套够用的规范自用就行。现代 CSS 布局有很多范式,但你不必全都理解全都用上。
至于现代布局的其他布局思路自然是有其应用场景才会出现的,你无法理解可能是还没遇到这样的场景。比如移动端电商 APP 的瀑布流布局,我是想不出靠前文说的三板斧怎么搞定在不同尺寸的手持设备上能够适配。
至于脑内布局引擎怎么工作的,只能说写多了脑回路就变成了 css 的样子。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/799232

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX