diff --git a/src/browser/StyleManager.zig b/src/browser/StyleManager.zig index 59d441515..0f8f8af9f 100644 --- a/src/browser/StyleManager.zig +++ b/src/browser/StyleManager.zig @@ -20,6 +20,7 @@ const std = @import("std"); const lp = @import("lightpanda"); const Frame = @import("Frame.zig"); +const Viewport = @import("Viewport.zig"); const units = @import("css/units.zig"); const CssParser = @import("css/Parser.zig"); @@ -40,7 +41,7 @@ const String = lp.String; const Allocator = std.mem.Allocator; // Tracks the CSS properties the renderless layout acts on (display, visibility, -// opacity, pointer-events, overflow) from +
content
+
content
+
content
+
+ + diff --git a/src/browser/webapi/CSS.zig b/src/browser/webapi/CSS.zig index 213064d7b..136b8a276 100644 --- a/src/browser/webapi/CSS.zig +++ b/src/browser/webapi/CSS.zig @@ -19,7 +19,6 @@ const std = @import("std"); const js = @import("../js/js.zig"); const Frame = @import("../Frame.zig"); -const units = @import("../css/units.zig"); const Tokenizer = @import("../css/Tokenizer.zig"); const CSS = @This(); @@ -27,18 +26,6 @@ _pad: bool = false, pub const init: CSS = .{}; -// parseDimension plus viewport-relative units, which the faux layout -// resolves against the page viewport. -pub fn parseDimensionViewport(value: []const u8, frame: *Frame) ?f64 { - const parsed = units.parse(value) catch return null; - return switch (parsed.unit) { - .none, .px => parsed.value, - .vh => parsed.value * @as(f64, @floatFromInt(frame.page.getViewport().height)) / 100.0, - .vw => parsed.value * @as(f64, @floatFromInt(frame.page.getViewport().width)) / 100.0, - else => null, - }; -} - // Extract the X value from a transfrom. This could come from a translate, // translatex, translate3d or matrix function. pub fn parseTranslateX(value: []const u8) f64 { diff --git a/src/browser/webapi/Element.zig b/src/browser/webapi/Element.zig index 89ba05b9b..741ba73a8 100644 --- a/src/browser/webapi/Element.zig +++ b/src/browser/webapi/Element.zig @@ -1497,27 +1497,34 @@ pub const Axis = enum { }; pub fn getElementAxis(self: *Element, frame: *Frame, comptime axis: Axis) Axis.State { - if (self.inlineStyle(frame)) |style| { - const decl = style.asCSSStyleDeclaration(); - if (CSS.parseDimensionViewport(decl.getPropertyValue(@tagName(axis), frame), frame)) |v| { + const tag = self.getTag(); + const root = tag == .html or tag == .body; + + if (self.ownerFrame(frame)) |owner| { + const style_manager = &owner._style_manager; + // Roots take only an inline size: a sheet's `height: 100vh` on body + // would shrink the box every synthetic position must fit in. + const size = if (root) style_manager.inlineSize(self, axis) else style_manager.declaredSize(self, axis); + if (size) |v| { return .{ .value = v, .explicit = true }; } } - switch (self.getTag()) { - // Root containers get large default size to contain descendant positions. - // With calculateDocumentPosition using linear depth scaling (100px per level), - // even very deep trees (100 levels) stay within 10,000px. - // 100M pixels is plausible for very long documents. - .html, .body => return .{ .value = if (axis == .width) 1920.0 else 100_000_000.0 }, - .img, .iframe => { - if (self.getAttributeSafe(comptime .wrap(@tagName(axis)))) |attr| { - if (std.fmt.parseFloat(f64, attr)) |parsed| { - return .{ .value = parsed, .explicit = true }; - } else |_| {} - } - }, - else => {}, + // Root containers get large default size to contain descendant positions. + // With calculateDocumentPosition using linear depth scaling (100px per level), + // even very deep trees (100 levels) stay within 10,000px. + // 100M pixels is plausible for very long documents. + if (root) { + return .{ .value = if (axis == .width) 1920.0 else 100_000_000.0 }; + } + + // Presentational attributes lose to CSS sizes. + if (tag == .img or tag == .iframe) { + if (self.getAttributeSafe(comptime .wrap(@tagName(axis)))) |attr| { + if (std.fmt.parseFloat(f64, attr)) |parsed| { + return .{ .value = parsed, .explicit = true }; + } else |_| {} + } } return .{ .value = 5.0 };