ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Yoga 样式(Styling)系统深度解析:默认样式、边框盒语义、边(Edge)与单位模型

Yoga 样式(Styling)系统深度解析:默认样式、边框盒语义、边(Edge)与单位模型 Yoga 样式Styling系统深度解析默认样式、边框盒语义、边Edge与单位模型【免费下载链接】yogaYoga is an embeddable layout engine targeting web standards.项目地址: https://gitcode.com/gh_mirrors/yog/yoga每个 Yoga 节点都关联一份独立的样式Style开发者可以用近似 CSS 的属性对节点进行布局定制但默认值、盒尺寸模型、边与单位等细节与 Web 存在系统性差异。本文以 Yoga 官方文档 website/docs/styling/index.md 为骨架结合 Style 类实现、边枚举、单位枚举、flex 解析逻辑 与 默认值测试完整讲解 Yoga 样式系统的默认值、边框盒语义、边层级、单位模型及非标准属性帮助你写出与引擎实际行为一致的布局代码。样式模型概览节点与 Style 的一一对应Yoga 中样式是附着在节点上的第一等公民每个节点都持有自己的样式数据布局算法在计算时读取这些数据。核心数据结构是facebook::yoga::Style类定义于 yoga/style/Style.h它集中管理以下类别的样式属性布局方向direction、flexDirection、justifyContent、alignContent、alignItems、alignSelf定位与溢出positionType、overflow、display弹性伸缩flex、flexGrow、flexShrink、flexBasis盒模型margin、padding、border、gap、positioninset尺寸dimensionwidth/height、minDimension、maxDimension、aspectRatio盒尺寸模型boxSizing从源码看Style.h 的私有字段定义 中所有枚举型属性都通过位域bitfield紧凑存储而数值类属性margin、padding、flex 等则通过StyleValueHandle句柄指向一个共享的StyleValuePool这是一种内存优化设计布局热路径中通过句柄直接解析已存储的值避免在栈上物化中间对象见 Style.h 中 resolve() 的注释。在 C API 层面每个属性都有对应的 getter/setter例如YGNodeStyleSetFlexGrow、YGNodeStyleGetFlexShrink等全部集中在 yoga/YGNodeStyle.cpp 中统一经由updateStyle模板写入并触发节点脏标记。默认样式接近 Web 的display: flex盒子但有四个关键差异Yoga 节点的默认样式大致等价于 Web 上一个设置了display: flex的盒子——事实上 Style.h 中display_的默认值正是Display::Flex。但与浏览器默认行为相比有四个值得注意的例外属性Yoga 默认值WebCSS Flexbox默认值flex-directioncolumnrowalign-contentflex-startstretchflex-shrink01positionrelativestatic这些默认值都可以在 Style.h 的字段初始化 中找到直接证据flexDirection_ : ... FlexDirection::Column;alignContent_ : ... Align::FlexStart;positionType_ : ... PositionType::Relative;以及常量DefaultFlexGrow 0.0f、DefaultFlexShrink 0.0fStyle.h#L45-L47其中还预留了WebDefaultFlexShrink 1.0f用于 Web 默认模式。默认值测试 对此有完整断言YGNodeStyleGetFlexDirection返回YGFlexDirectionColumn、YGNodeStyleGetAlignContent返回YGAlignFlexStart、YGNodeStyleGetFlexShrink返回0、YGNodeStyleGetPositionType返回YGPositionTypeRelative。用 UseWebDefaults 对齐 Web 默认值对于前三个差异flex-direction、align-content、flex-shrinkYoga 提供UseWebDefaults配置开关让整棵树的默认行为对齐浏览器。开启后 YGNodeStyleGetFlexShrink 在未显式设置时会返回 1.0flex-direction变为rowalign-content变为stretch。C 语言示例#include yoga/Yoga.h YGConfigRef config YGConfigNew(); YGConfigSetUseWebDefaults(config, true); // 开启 Web 默认值 YGNodeRef root YGNodeNewWithConfig(config);测试文件中的 assert_webdefault_values 精确验证了开启后的结果YGFlexDirectionRow、YGAlignStretch、flexShrink 1.0f。兼容性警告UseWebDefaults标志在position: static引入之前就已存在。出于向后兼容的考虑它不会改变默认的position值仍为relative。也就是说即使开启 Web 默认值也无法通过它获得 CSS 的static定位默认行为。这是 官方配置文档 中明确标注的注意事项。从实现看该标志存储于 Config 类中useWebDefaults_ : 1 false默认关闭属于配置级而非节点级属性——一个 Config 可以被多个节点共享因此开启后会影响所有使用该 Config 创建的节点。更细粒度的行为控制如针对个别历史行为偏差的修正则通过 Errata 机制完成详见 配置文档。Box Sizing一切按border-box计算Yoga 在计算尺寸时始终表现得如同设置了 CSS 的box-sizing: border-box你指定的宽度/高度已经包含该盒子的 padding 和 border 空间无需像 Web 的默认content-box那样手动累加。源码中的直接证据Style.h 中boxSizing_的默认值为BoxSizing::BorderBoxresolvedMinDimension / resolvedMaxDimension 中可以看到当boxSizing为ContentBox时解析出的 min/max 值会自动加上对应轴向的 padding 与 bordercomputePaddingAndBorderForDimension而BorderBox模式直接返回原值——这正是指定尺寸包含 padding/border的底层实现弹性基准flex basis的解析同样遵守该语义Node::resolveFlexBasis 在BorderBox模式下直接返回解析值ContentBox模式才追加 padding/border。对开发者而言这意味着给节点设置width: 100再加padding: 10最终占用的布局宽度仍然是100padding 从这 100 之内扣除。这与许多 UI 框架如 React Native、Flutter 的部分容器的行为一致也让 Yoga 的尺寸语义可预测。Edges三层次的边模型与解析优先级margin、padding、positioninset和border都是针对边Edge设置的。Yoga 的边模型分为三个层次完整枚举见 yoga/enums/Edge.h相对书写方向的边logicalStart/End——跟随布局方向LTR/RTL自动翻转物理边physicalLeft/Top/Right/Bottom——固定指向盒子的物理方位边的集合groupHorizontal左右、Vertical上下、All四周。一个样式值可以同时针对多个 Edge 设置取值优先级严格按上述顺序start/end 物理边 horizontal/verticalall。也就是说同时设置All与Left时Left生效同时设置Left与Start在 LTR 下时Start生效。这一优先级在 Style.h 的 computeLeftEdge / computeRightEdge 等内部解析函数 中有清晰的实现例如computeLeftEdge的判定链为——LTR 且设置了Start→ 取StartRTL 且设置了End→ 取End方向感知的关键所在否则设置了Left→ 取Left否则设置了Horizontal→ 取Horizontal否则取All。顶部/底部则简化为Top/Bottom→Vertical→AllcomputeTopEdge。margin、padding、position、border 四类属性共用这套解析逻辑computeMargin、computePadding、computeBorder、computePosition见 Style.h#L818-L878保证全属性行为一致。方向RTL的影响由于Start/End是逻辑边在 RTL 布局下左右会互换。direction属性在 Style.h#L900 默认Direction::Inherit继承父节点最终由 Node::resolveDirection 在布局时解析未指定时回退为 LTR。更深入的逻辑边与物理边换算可参考 layout-direction.mdx 与 margin-padding-border.mdx。Units没有px、em只有 Points 与百分比Yoga不识别 CSS 单位如px、em、rem。引擎内部只处理两类数值语义points点一种任意的、规范的绝对单位通常由宿主框架映射为显示独立像素display-independent pixels。所有数值型样式属性width、margin、padding、border、gap、flex-basis 等都以 point 为单位。percentage百分比相对于某个参考长度通常是父节点对应轴向的尺寸的比例值。其他单位如em、vw必须在传入 Yoga 之前由宿主层完成绝对化absolutize换算。源码层面yoga/enums/Unit.h 定义了完整的单位枚举单位含义Undefined未定义缺省值Point绝对点数Percent百分比Auto关键字autoMaxContent关键字max-content内部尺寸FitContent关键字fit-contentStretch关键字stretch长度值类型由 yoga/style/StyleLength.h 实现其类注释明确将其建模为 CSSlength-percentage值。构造方式只有三种入口StyleLength::points(v)、StyleLength::percent(v)、StyleLength::ofAuto()且构造函数是私有的——从设计上杜绝了非法或冗余的单位组合。百分比解析发生在resolve(referenceLength)方法中value * referenceLength * 0.01f即相对参考长度按比例放大。另外NaN或无穷值在构造时会被规约为undefined见 StyleLength.h#L32-L42避免非法值污染布局。非标准属性aspect-ratio与flex简写aspect-ratio早于 CSS 规范、行为可能有差异Yoga 的aspect-ratio属性早于同名 CSS 属性引入因此在边界行为上可能和 Web 标准存在细微差别这些差异有望在未来版本中逐步对齐。从 Style.h 的 setAspectRatio 可以看到一个已对齐 Web 的细节退化degenerate比率——0或无穷值——会被当作auto处理注释中明确引用了 CSS Sizing 4 规范drafts.csswg.org/css-sizing-4/#valdef-aspect-ratio-ratio。也就是说aspect-ratio: 0不会让盒子塌缩为零而是回退到自动尺寸。完整行为说明与示例见 aspect-ratio.mdx。flex简写正数为 grow负数为 shrinkYoga 的flex简写与 CSS 存在显著差异它不会像 CSS 那样展开为flex-grow / flex-shrink / flex-basis三件套而是采用正数即 grow负数即 shrink的极简语义——flex: 2相当于flex-grow: 2flex: -2相当于flex-shrink: 2。该逻辑在 Node::resolveFlexGrow / resolveFlexShrink 中实现resolveFlexGrow显式flexGrow优先否则若flex为正数flexGrow取该值resolveFlexShrink显式flexShrink优先否则在非 Web 默认模式下若flex为负数flexShrink取其绝对值兜底值取决于配置useWebDefaults开启时为1.0否则为0根节点无 owner的 grow/shrink 恒为0。此外flex简写还会影响 flex-basis 的推导processFlexBasis 在flexBasis为auto/未定义、且flex为正数时非 Web 默认模式下将 basis 视为0点即flex: 1相当于basis 为 0 的伸缩Web 默认模式下则保持auto。这与 CSSflex: number展开为flex: number 1 0%的部分语义一致但 grow/shrink 的展开方式完全不同。完整讨论见 flex-basis-grow-shrink.mdx。延伸阅读配置 YogaConfig / Errata / PointScaleFactorUseWebDefaults、Errata 兼容模式与像素网格舍入的完整配置方式width-height.mdx 与 min-max-width-height.mdx尺寸与 min/max 约束在 points/percent 下的行为margin-padding-border.mdx 与 insets.mdx边模型的具体用法position.mdx默认relative定位与static/absolute的差异display.mdx默认flex显示模式及contents等特殊值源码与测试Style 定义、默认值测试、样式 API【免费下载链接】yogaYoga is an embeddable layout engine targeting web standards.项目地址: https://gitcode.com/gh_mirrors/yog/yoga创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表