1use crate::values::{LengthPercentage, LengthPercentageAuto, LengthPercentageNone};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum DisplayOuter {
8 Block,
9 Inline,
10 None,
11}
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum DisplayInner {
16 Flow,
17 FlowRoot,
18 Flex,
19 Grid,
20 Table,
21 TableRowGroup,
22 TableRow,
23 TableCell,
24 TableColumn,
25 TableColumnGroup,
26 TableCaption,
27 TableHeaderGroup,
28 TableFooterGroup,
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub struct Display {
34 pub outer: DisplayOuter,
35 pub inner: DisplayInner,
36}
37
38impl Display {
39 pub const BLOCK: Self = Self {
40 outer: DisplayOuter::Block,
41 inner: DisplayInner::Flow,
42 };
43 pub const INLINE: Self = Self {
44 outer: DisplayOuter::Inline,
45 inner: DisplayInner::Flow,
46 };
47 pub const INLINE_BLOCK: Self = Self {
48 outer: DisplayOuter::Inline,
49 inner: DisplayInner::FlowRoot,
50 };
51 pub const FLEX: Self = Self {
52 outer: DisplayOuter::Block,
53 inner: DisplayInner::Flex,
54 };
55 pub const INLINE_FLEX: Self = Self {
56 outer: DisplayOuter::Inline,
57 inner: DisplayInner::Flex,
58 };
59 pub const GRID: Self = Self {
60 outer: DisplayOuter::Block,
61 inner: DisplayInner::Grid,
62 };
63 pub const INLINE_GRID: Self = Self {
64 outer: DisplayOuter::Inline,
65 inner: DisplayInner::Grid,
66 };
67 pub const TABLE: Self = Self {
68 outer: DisplayOuter::Block,
69 inner: DisplayInner::Table,
70 };
71 pub const TABLE_ROW: Self = Self {
72 outer: DisplayOuter::Block,
73 inner: DisplayInner::TableRow,
74 };
75 pub const TABLE_CELL: Self = Self {
76 outer: DisplayOuter::Block,
77 inner: DisplayInner::TableCell,
78 };
79 pub const TABLE_ROW_GROUP: Self = Self {
80 outer: DisplayOuter::Block,
81 inner: DisplayInner::TableRowGroup,
82 };
83 pub const TABLE_COLUMN: Self = Self {
84 outer: DisplayOuter::Block,
85 inner: DisplayInner::TableColumn,
86 };
87 pub const TABLE_COLUMN_GROUP: Self = Self {
88 outer: DisplayOuter::Block,
89 inner: DisplayInner::TableColumnGroup,
90 };
91 pub const TABLE_CAPTION: Self = Self {
92 outer: DisplayOuter::Block,
93 inner: DisplayInner::TableCaption,
94 };
95 pub const TABLE_HEADER_GROUP: Self = Self {
96 outer: DisplayOuter::Block,
97 inner: DisplayInner::TableHeaderGroup,
98 };
99 pub const TABLE_FOOTER_GROUP: Self = Self {
100 outer: DisplayOuter::Block,
101 inner: DisplayInner::TableFooterGroup,
102 };
103 pub const NONE: Self = Self {
104 outer: DisplayOuter::None,
105 inner: DisplayInner::Flow,
106 };
107 pub const FLOW_ROOT: Self = Self {
108 outer: DisplayOuter::Block,
109 inner: DisplayInner::FlowRoot,
110 };
111
112 pub fn is_none(&self) -> bool {
113 self.outer == DisplayOuter::None
114 }
115
116 pub fn is_block_level(&self) -> bool {
117 self.outer == DisplayOuter::Block
118 }
119
120 pub fn is_inline_level(&self) -> bool {
121 self.outer == DisplayOuter::Inline
122 }
123
124 pub fn establishes_bfc(&self) -> bool {
125 matches!(
126 self.inner,
127 DisplayInner::FlowRoot | DisplayInner::Flex | DisplayInner::Grid | DisplayInner::Table
128 )
129 }
130
131 pub fn is_table_part(&self) -> bool {
132 matches!(
133 self.inner,
134 DisplayInner::Table
135 | DisplayInner::TableRow
136 | DisplayInner::TableCell
137 | DisplayInner::TableRowGroup
138 | DisplayInner::TableColumn
139 | DisplayInner::TableColumnGroup
140 | DisplayInner::TableCaption
141 | DisplayInner::TableHeaderGroup
142 | DisplayInner::TableFooterGroup
143 )
144 }
145}
146
147impl Default for Display {
148 fn default() -> Self {
149 Self::INLINE
150 }
151}
152
153#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
155pub enum Position {
156 #[default]
157 Static,
158 Relative,
159 Absolute,
160 Fixed,
161 Sticky,
162}
163
164impl Position {
165 pub fn is_positioned(&self) -> bool {
166 !matches!(self, Position::Static)
167 }
168
169 pub fn is_absolutely_positioned(&self) -> bool {
170 matches!(self, Position::Absolute | Position::Fixed)
171 }
172
173 pub fn is_in_flow(&self) -> bool {
174 matches!(
175 self,
176 Position::Static | Position::Relative | Position::Sticky
177 )
178 }
179}
180
181#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
183pub enum BoxSizing {
184 #[default]
185 ContentBox,
186 BorderBox,
187}
188
189#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
191pub enum Float {
192 #[default]
193 None,
194 Left,
195 Right,
196}
197
198#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
200pub enum Clear {
201 #[default]
202 None,
203 Left,
204 Right,
205 Both,
206}
207
208#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
210pub enum Overflow {
211 #[default]
212 Visible,
213 Hidden,
214 Scroll,
215 Auto,
216}
217
218#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
220pub enum TextAlign {
221 #[default]
222 Left,
223 Right,
224 Center,
225 Justify,
226}
227
228#[derive(Debug, Clone, Copy, PartialEq, Default)]
230pub enum VerticalAlign {
231 #[default]
232 Baseline,
233 Top,
234 Middle,
235 Bottom,
236 Length(f32),
237}
238
239#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
241pub enum WhiteSpace {
242 #[default]
243 Normal,
244 Nowrap,
245 Pre,
246 PreWrap,
247 PreLine,
248}
249
250impl WhiteSpace {
251 pub fn preserves_newlines(&self) -> bool {
252 matches!(
253 self,
254 WhiteSpace::Pre | WhiteSpace::PreWrap | WhiteSpace::PreLine
255 )
256 }
257
258 pub fn collapses_spaces(&self) -> bool {
259 matches!(
260 self,
261 WhiteSpace::Normal | WhiteSpace::Nowrap | WhiteSpace::PreLine
262 )
263 }
264
265 pub fn wraps(&self) -> bool {
266 matches!(
267 self,
268 WhiteSpace::Normal | WhiteSpace::PreWrap | WhiteSpace::PreLine
269 )
270 }
271}
272
273#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
277pub enum FlexDirection {
278 #[default]
279 Row,
280 RowReverse,
281 Column,
282 ColumnReverse,
283}
284
285impl FlexDirection {
286 pub fn is_row(&self) -> bool {
287 matches!(self, FlexDirection::Row | FlexDirection::RowReverse)
288 }
289
290 pub fn is_column(&self) -> bool {
291 !self.is_row()
292 }
293
294 pub fn is_reverse(&self) -> bool {
295 matches!(
296 self,
297 FlexDirection::RowReverse | FlexDirection::ColumnReverse
298 )
299 }
300}
301
302#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
304pub enum FlexWrap {
305 #[default]
306 Nowrap,
307 Wrap,
308 WrapReverse,
309}
310
311#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
313pub enum AlignItems {
314 #[default]
315 Stretch,
316 FlexStart,
317 FlexEnd,
318 Center,
319 Baseline,
320 Start,
321 End,
322}
323
324#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
326pub enum AlignSelf {
327 #[default]
328 Auto,
329 Stretch,
330 FlexStart,
331 FlexEnd,
332 Center,
333 Baseline,
334 Start,
335 End,
336}
337
338#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
340pub enum JustifyContent {
341 #[default]
342 FlexStart,
343 FlexEnd,
344 Center,
345 SpaceBetween,
346 SpaceAround,
347 SpaceEvenly,
348 Start,
349 End,
350}
351
352#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
354pub enum AlignContent {
355 #[default]
356 Stretch,
357 FlexStart,
358 FlexEnd,
359 Center,
360 SpaceBetween,
361 SpaceAround,
362 SpaceEvenly,
363 Start,
364 End,
365}
366
367#[derive(Debug, Clone, PartialEq, Default)]
371pub enum TrackSizingFunction {
372 Length(f32),
374 Percentage(f32),
376 Fr(f32),
378 MinContent,
380 MaxContent,
382 #[default]
384 Auto,
385 MinMax(Box<TrackSizingFunction>, Box<TrackSizingFunction>),
387 FitContent(f32),
389}
390
391#[derive(Debug, Clone, PartialEq)]
393pub struct TrackDefinition {
394 pub sizing: TrackSizingFunction,
395 pub line_name: Option<String>,
396}
397
398impl TrackDefinition {
399 pub fn new(sizing: TrackSizingFunction) -> Self {
400 Self {
401 sizing,
402 line_name: None,
403 }
404 }
405}
406
407#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
409pub enum GridAutoFlow {
410 #[default]
411 Row,
412 Column,
413 RowDense,
414 ColumnDense,
415}
416
417#[derive(Debug, Clone, PartialEq, Default)]
419pub enum GridPlacement {
420 #[default]
421 Auto,
422 Line(i32),
423 Span(u32),
424 Named(String),
425}
426
427#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
431pub enum TableLayout {
432 #[default]
433 Auto,
434 Fixed,
435}
436
437#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
439pub enum BorderCollapse {
440 #[default]
441 Separate,
442 Collapse,
443}
444
445#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
447pub enum CaptionSide {
448 #[default]
449 Top,
450 Bottom,
451}
452
453#[derive(Debug, Clone, PartialEq)]
457pub struct ComputedStyle {
458 pub display: Display,
460 pub position: Position,
461 pub float: Float,
462 pub clear: Clear,
463
464 pub box_sizing: BoxSizing,
466 pub width: LengthPercentageAuto,
467 pub height: LengthPercentageAuto,
468 pub min_width: LengthPercentage,
469 pub min_height: LengthPercentage,
470 pub max_width: LengthPercentageNone,
471 pub max_height: LengthPercentageNone,
472
473 pub margin_top: LengthPercentageAuto,
474 pub margin_right: LengthPercentageAuto,
475 pub margin_bottom: LengthPercentageAuto,
476 pub margin_left: LengthPercentageAuto,
477
478 pub padding_top: LengthPercentage,
479 pub padding_right: LengthPercentage,
480 pub padding_bottom: LengthPercentage,
481 pub padding_left: LengthPercentage,
482
483 pub border_top_width: f32,
484 pub border_right_width: f32,
485 pub border_bottom_width: f32,
486 pub border_left_width: f32,
487
488 pub top: LengthPercentageAuto,
490 pub right: LengthPercentageAuto,
491 pub bottom: LengthPercentageAuto,
492 pub left: LengthPercentageAuto,
493
494 pub overflow_x: Overflow,
496 pub overflow_y: Overflow,
497
498 pub text_align: TextAlign,
500 pub vertical_align: VerticalAlign,
501 pub line_height: f32,
502 pub white_space: WhiteSpace,
503
504 pub flex_direction: FlexDirection,
506 pub flex_wrap: FlexWrap,
507 pub flex_grow: f32,
508 pub flex_shrink: f32,
509 pub flex_basis: LengthPercentageAuto,
510 pub align_items: AlignItems,
511 pub align_self: AlignSelf,
512 pub align_content: AlignContent,
513 pub justify_content: JustifyContent,
514 pub order: i32,
515
516 pub grid_template_rows: Vec<TrackDefinition>,
518 pub grid_template_columns: Vec<TrackDefinition>,
519 pub grid_auto_rows: Vec<TrackSizingFunction>,
520 pub grid_auto_columns: Vec<TrackSizingFunction>,
521 pub grid_auto_flow: GridAutoFlow,
522 pub row_gap: f32,
523 pub column_gap: f32,
524
525 pub grid_row_start: GridPlacement,
527 pub grid_row_end: GridPlacement,
528 pub grid_column_start: GridPlacement,
529 pub grid_column_end: GridPlacement,
530
531 pub table_layout: TableLayout,
533 pub border_collapse: BorderCollapse,
534 pub border_spacing: f32,
535 pub caption_side: CaptionSide,
536
537 pub z_index: crate::values::NumberOrAuto,
539}
540
541impl Default for ComputedStyle {
542 fn default() -> Self {
543 Self {
544 display: Display::INLINE,
545 position: Position::Static,
546 float: Float::None,
547 clear: Clear::None,
548
549 box_sizing: BoxSizing::ContentBox,
550 width: LengthPercentageAuto::Auto,
551 height: LengthPercentageAuto::Auto,
552 min_width: LengthPercentage::Length(0.0),
553 min_height: LengthPercentage::Length(0.0),
554 max_width: LengthPercentageNone::None,
555 max_height: LengthPercentageNone::None,
556
557 margin_top: LengthPercentageAuto::px(0.0),
558 margin_right: LengthPercentageAuto::px(0.0),
559 margin_bottom: LengthPercentageAuto::px(0.0),
560 margin_left: LengthPercentageAuto::px(0.0),
561
562 padding_top: LengthPercentage::Length(0.0),
563 padding_right: LengthPercentage::Length(0.0),
564 padding_bottom: LengthPercentage::Length(0.0),
565 padding_left: LengthPercentage::Length(0.0),
566
567 border_top_width: 0.0,
568 border_right_width: 0.0,
569 border_bottom_width: 0.0,
570 border_left_width: 0.0,
571
572 top: LengthPercentageAuto::Auto,
573 right: LengthPercentageAuto::Auto,
574 bottom: LengthPercentageAuto::Auto,
575 left: LengthPercentageAuto::Auto,
576
577 overflow_x: Overflow::Visible,
578 overflow_y: Overflow::Visible,
579
580 text_align: TextAlign::Left,
581 vertical_align: VerticalAlign::Baseline,
582 line_height: 1.2,
583 white_space: WhiteSpace::Normal,
584
585 flex_direction: FlexDirection::Row,
586 flex_wrap: FlexWrap::Nowrap,
587 flex_grow: 0.0,
588 flex_shrink: 1.0,
589 flex_basis: LengthPercentageAuto::Auto,
590 align_items: AlignItems::Stretch,
591 align_self: AlignSelf::Auto,
592 align_content: AlignContent::Stretch,
593 justify_content: JustifyContent::FlexStart,
594 order: 0,
595
596 grid_template_rows: Vec::new(),
597 grid_template_columns: Vec::new(),
598 grid_auto_rows: Vec::new(),
599 grid_auto_columns: Vec::new(),
600 grid_auto_flow: GridAutoFlow::Row,
601 row_gap: 0.0,
602 column_gap: 0.0,
603
604 grid_row_start: GridPlacement::Auto,
605 grid_row_end: GridPlacement::Auto,
606 grid_column_start: GridPlacement::Auto,
607 grid_column_end: GridPlacement::Auto,
608
609 table_layout: TableLayout::Auto,
610 border_collapse: BorderCollapse::Separate,
611 border_spacing: 0.0,
612 caption_side: CaptionSide::Top,
613
614 z_index: crate::values::NumberOrAuto::Auto,
615 }
616 }
617}
618
619impl ComputedStyle {
620 pub fn block() -> Self {
622 Self {
623 display: Display::BLOCK,
624 ..Default::default()
625 }
626 }
627
628 pub fn inline() -> Self {
630 Self::default()
631 }
632
633 pub fn establishes_bfc(&self) -> bool {
635 self.display.establishes_bfc()
636 || self.overflow_x != Overflow::Visible
637 || self.overflow_y != Overflow::Visible
638 || self.float != Float::None
639 || self.position.is_absolutely_positioned()
640 }
641
642 pub fn is_out_of_flow(&self) -> bool {
644 self.position.is_absolutely_positioned() || self.float != Float::None
645 }
646}