Skip to main content

taffy/style/
mod.rs

1//! A typed representation of [CSS style properties](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) in Rust. Used as input to layout computation.
2mod alignment;
3mod available_space;
4mod compact_length;
5mod dimension;
6
7#[cfg(feature = "block_layout")]
8mod block;
9#[cfg(feature = "flexbox")]
10mod flex;
11#[cfg(feature = "float_layout")]
12mod float;
13#[cfg(feature = "grid")]
14mod grid;
15
16pub use self::alignment::{AlignContent, AlignItems, AlignSelf, JustifyContent, JustifyItems, JustifySelf};
17pub use self::available_space::AvailableSpace;
18pub use self::compact_length::CompactLength;
19pub use self::dimension::{Dimension, LengthPercentage, LengthPercentageAuto};
20use crate::sys::DefaultCheapStr;
21
22#[cfg(feature = "block_layout")]
23pub use self::block::{BlockContainerStyle, BlockItemStyle, TextAlign};
24#[cfg(feature = "flexbox")]
25pub use self::flex::{FlexDirection, FlexWrap, FlexboxContainerStyle, FlexboxItemStyle};
26#[cfg(feature = "float_layout")]
27pub use self::float::{Clear, Float, FloatDirection};
28#[cfg(feature = "grid")]
29pub use self::grid::{
30    GenericGridPlacement, GenericGridTemplateComponent, GenericRepetition, GridAutoFlow, GridAutoTracks,
31    GridContainerStyle, GridItemStyle, GridPlacement, GridTemplateComponent, GridTemplateRepetition,
32    GridTemplateTracks, MaxTrackSizingFunction, MinTrackSizingFunction, RepetitionCount, TrackSizingFunction,
33};
34#[cfg(feature = "grid")]
35pub(crate) use self::grid::{GridAreaAxis, GridAreaEnd};
36#[cfg(feature = "grid")]
37pub use self::grid::{GridTemplateArea, NamedGridLine, TemplateLineNames};
38#[cfg(feature = "grid")]
39pub(crate) use self::grid::{NonNamedGridPlacement, OriginZeroGridPlacement};
40
41use crate::geometry::{Point, Rect, Size};
42use crate::style_helpers::TaffyAuto as _;
43use core::fmt::Debug;
44
45#[cfg(feature = "grid")]
46use crate::geometry::Line;
47#[cfg(feature = "serde")]
48use crate::style_helpers;
49#[cfg(feature = "grid")]
50use crate::util::sys::GridTrackVec;
51
52use crate::sys::String;
53
54/// Trait that represents a cheaply clonable string. If you're unsure what to use here
55/// consider `Arc<str>` or `string_cache::Atom`.
56#[cfg(any(feature = "alloc", feature = "std"))]
57pub trait CheapCloneStr:
58    AsRef<str> + for<'a> From<&'a str> + From<String> + PartialEq + Eq + Clone + Default + Debug + 'static
59{
60}
61#[cfg(any(feature = "alloc", feature = "std"))]
62impl<T> CheapCloneStr for T where
63    T: AsRef<str> + for<'a> From<&'a str> + From<String> + PartialEq + Eq + Clone + Default + Debug + 'static
64{
65}
66
67/// Trait that represents a cheaply clonable string. If you're unsure what to use here
68/// consider `Arc<str>` or `string_cache::Atom`.
69#[cfg(not(any(feature = "alloc", feature = "std")))]
70pub trait CheapCloneStr {}
71#[cfg(not(any(feature = "alloc", feature = "std")))]
72impl<T> CheapCloneStr for T {}
73
74/// The core set of styles that are shared between all CSS layout nodes
75///
76/// Note that all methods come with a default implementation which simply returns the default value for that style property
77/// but this is a just a convenience to save on boilerplate for styles that your implementation doesn't support. You will need
78/// to override the default implementation for each style property that your style type actually supports.
79pub trait CoreStyle {
80    /// The type of custom identifiers used to identify named grid lines and areas
81    type CustomIdent: CheapCloneStr;
82
83    /// Which box generation mode should be used
84    #[inline(always)]
85    fn box_generation_mode(&self) -> BoxGenerationMode {
86        BoxGenerationMode::DEFAULT
87    }
88    /// Is block layout?
89    #[inline(always)]
90    fn is_block(&self) -> bool {
91        false
92    }
93    /// Is it a compressible replaced element?
94    /// <https://drafts.csswg.org/css-sizing-3/#min-content-zero>
95    #[inline(always)]
96    fn is_compressible_replaced(&self) -> bool {
97        false
98    }
99    /// Which box do size styles apply to
100    #[inline(always)]
101    fn box_sizing(&self) -> BoxSizing {
102        BoxSizing::BorderBox
103    }
104
105    /// The direction of text, table and grid columns, and horizontal overflow.
106    #[inline(always)]
107    fn direction(&self) -> Direction {
108        Direction::Ltr
109    }
110
111    // Overflow properties
112    /// How children overflowing their container should affect layout
113    #[inline(always)]
114    fn overflow(&self) -> Point<Overflow> {
115        Style::<Self::CustomIdent>::DEFAULT.overflow
116    }
117    /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes.
118    #[inline(always)]
119    fn scrollbar_width(&self) -> f32 {
120        0.0
121    }
122
123    // Position properties
124    /// What should the `position` value of this struct use as a base offset?
125    #[inline(always)]
126    fn position(&self) -> Position {
127        Style::<Self::CustomIdent>::DEFAULT.position
128    }
129    /// How should the position of this element be tweaked relative to the layout defined?
130    #[inline(always)]
131    fn inset(&self) -> Rect<LengthPercentageAuto> {
132        Style::<Self::CustomIdent>::DEFAULT.inset
133    }
134
135    // Size properies
136    /// Sets the initial size of the item
137    #[inline(always)]
138    fn size(&self) -> Size<Dimension> {
139        Style::<Self::CustomIdent>::DEFAULT.size
140    }
141    /// Controls the minimum size of the item
142    #[inline(always)]
143    fn min_size(&self) -> Size<Dimension> {
144        Style::<Self::CustomIdent>::DEFAULT.min_size
145    }
146    /// Controls the maximum size of the item
147    #[inline(always)]
148    fn max_size(&self) -> Size<Dimension> {
149        Style::<Self::CustomIdent>::DEFAULT.max_size
150    }
151    /// Sets the preferred aspect ratio for the item
152    /// The ratio is calculated as width divided by height.
153    #[inline(always)]
154    fn aspect_ratio(&self) -> Option<f32> {
155        Style::<Self::CustomIdent>::DEFAULT.aspect_ratio
156    }
157
158    // Spacing Properties
159    /// How large should the margin be on each side?
160    #[inline(always)]
161    fn margin(&self) -> Rect<LengthPercentageAuto> {
162        Style::<Self::CustomIdent>::DEFAULT.margin
163    }
164    /// How large should the padding be on each side?
165    #[inline(always)]
166    fn padding(&self) -> Rect<LengthPercentage> {
167        Style::<Self::CustomIdent>::DEFAULT.padding
168    }
169    /// How large should the border be on each side?
170    #[inline(always)]
171    fn border(&self) -> Rect<LengthPercentage> {
172        Style::<Self::CustomIdent>::DEFAULT.border
173    }
174}
175
176/// Sets the layout used for the children of this node
177///
178/// The default values depends on on which feature flags are enabled. The order of precedence is: Flex, Grid, Block, None.
179#[derive(Copy, Clone, PartialEq, Eq, Debug)]
180#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
181pub enum Display {
182    /// The children will follow the block layout algorithm
183    #[cfg(feature = "block_layout")]
184    Block,
185    /// The children will follow the flexbox layout algorithm
186    #[cfg(feature = "flexbox")]
187    Flex,
188    /// The children will follow the CSS Grid layout algorithm
189    #[cfg(feature = "grid")]
190    Grid,
191    /// The node is hidden, and it's children will also be hidden
192    None,
193}
194
195impl Display {
196    /// The default Display mode
197    #[cfg(feature = "flexbox")]
198    pub const DEFAULT: Display = Display::Flex;
199
200    /// The default Display mode
201    #[cfg(all(feature = "grid", not(feature = "flexbox")))]
202    pub const DEFAULT: Display = Display::Grid;
203
204    /// The default Display mode
205    #[cfg(all(feature = "block_layout", not(feature = "flexbox"), not(feature = "grid")))]
206    pub const DEFAULT: Display = Display::Block;
207
208    /// The default Display mode
209    #[cfg(all(not(feature = "flexbox"), not(feature = "grid"), not(feature = "block_layout")))]
210    pub const DEFAULT: Display = Display::None;
211}
212
213impl Default for Display {
214    fn default() -> Self {
215        Self::DEFAULT
216    }
217}
218
219#[cfg(feature = "parse")]
220crate::util::parse::impl_parse_for_keyword_enum!(Display,
221    "none" => None,
222    #[cfg(feature = "flexbox")]
223    "flex" => Flex,
224    #[cfg(feature = "grid")]
225    "grid" => Grid,
226    #[cfg(feature = "block_layout")]
227    "block" => Block,
228);
229
230impl core::fmt::Display for Display {
231    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
232        match self {
233            Display::None => write!(f, "NONE"),
234            #[cfg(feature = "block_layout")]
235            Display::Block => write!(f, "BLOCK"),
236            #[cfg(feature = "flexbox")]
237            Display::Flex => write!(f, "FLEX"),
238            #[cfg(feature = "grid")]
239            Display::Grid => write!(f, "GRID"),
240        }
241    }
242}
243
244/// An abstracted version of the CSS `display` property where any value other than "none" is represented by "normal"
245/// See: <https://www.w3.org/TR/css-display-3/#box-generation>
246#[derive(Copy, Clone, PartialEq, Eq, Debug)]
247#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
248pub enum BoxGenerationMode {
249    /// The node generates a box in the regular way
250    Normal,
251    /// The node and it's descendants generate no boxes (they are hidden)
252    None,
253}
254
255impl BoxGenerationMode {
256    /// The default of BoxGenerationMode
257    pub const DEFAULT: BoxGenerationMode = BoxGenerationMode::Normal;
258}
259
260impl Default for BoxGenerationMode {
261    fn default() -> Self {
262        Self::DEFAULT
263    }
264}
265
266/// The positioning strategy for this item.
267///
268/// This controls both how the origin is determined for the [`Style::position`] field,
269/// and whether or not the item will be controlled by flexbox's layout algorithm.
270///
271/// WARNING: this enum follows the behavior of [CSS's `position` property](https://developer.mozilla.org/en-US/docs/Web/CSS/position),
272/// which can be unintuitive.
273///
274/// [`Position::Relative`] is the default value, in contrast to the default behavior in CSS.
275#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
276#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
277pub enum Position {
278    /// The offset is computed relative to the final position given by the layout algorithm.
279    /// Offsets do not affect the position of any other items; they are effectively a correction factor applied at the end.
280    #[default]
281    Relative,
282    /// The offset is computed relative to this item's closest positioned ancestor, if any.
283    /// Otherwise, it is placed relative to the origin.
284    /// No space is created for the item in the page layout, and its size will not be altered.
285    ///
286    /// WARNING: to opt-out of layouting entirely, you must use [`Display::None`] instead on your [`Style`] object.
287    Absolute,
288}
289
290#[cfg(feature = "parse")]
291crate::util::parse::impl_parse_for_keyword_enum!(Position,
292    "relative" => Relative,
293    "absolute" => Absolute,
294);
295
296/// Specifies whether size styles for this node are assigned to the node's "content box" or "border box"
297///
298/// - The "content box" is the node's inner size excluding padding, border and margin
299/// - The "border box" is the node's outer size including padding and border (but still excluding margin)
300///
301/// This property modifies the application of the following styles:
302///
303///   - `size`
304///   - `min_size`
305///   - `max_size`
306///   - `flex_basis`
307///
308/// See <https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing>
309#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
310#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
311pub enum BoxSizing {
312    /// Size styles such size, min_size, max_size specify the box's "border box" (the size excluding margin but including padding/border)
313    #[default]
314    BorderBox,
315    /// Size styles such size, min_size, max_size specify the box's "content box" (the size excluding padding/border/margin)
316    ContentBox,
317}
318
319#[cfg(feature = "parse")]
320crate::util::parse::impl_parse_for_keyword_enum!(BoxSizing,
321    "border-box" => BorderBox,
322    "content-box" => ContentBox,
323);
324
325/// How children overflowing their container should affect layout
326///
327/// In CSS the primary effect of this property is to control whether contents of a parent container that overflow that container should
328/// be displayed anyway, be clipped, or trigger the container to become a scroll container. However it also has secondary effects on layout,
329/// the main ones being:
330///
331///   - The automatic minimum size Flexbox/CSS Grid items with non-`Visible` overflow is `0` rather than being content based
332///   - `Overflow::Scroll` nodes have space in the layout reserved for a scrollbar (width controlled by the `scrollbar_width` property)
333///
334/// In Taffy, we only implement the layout related secondary effects as we are not concerned with drawing/painting. The amount of space reserved for
335/// a scrollbar is controlled by the `scrollbar_width` property. If this is `0` then `Scroll` behaves identically to `Hidden`.
336///
337/// <https://developer.mozilla.org/en-US/docs/Web/CSS/overflow>
338#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
339#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
340pub enum Overflow {
341    /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content.
342    /// Content that overflows this node *should* contribute to the scroll region of its parent.
343    #[default]
344    Visible,
345    /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content.
346    /// Content that overflows this node should *not* contribute to the scroll region of its parent.
347    Clip,
348    /// The automatic minimum size of this node as a flexbox/grid item should be `0`.
349    /// Content that overflows this node should *not* contribute to the scroll region of its parent.
350    Hidden,
351    /// The automatic minimum size of this node as a flexbox/grid item should be `0`. Additionally, space should be reserved
352    /// for a scrollbar. The amount of space reserved is controlled by the `scrollbar_width` property.
353    /// Content that overflows this node should *not* contribute to the scroll region of its parent.
354    Scroll,
355}
356
357impl Overflow {
358    /// Returns true for overflow modes that contain their contents (`Overflow::Hidden`, `Overflow::Scroll`, `Overflow::Auto`)
359    /// or else false for overflow modes that allow their contains to spill (`Overflow::Visible`).
360    #[inline(always)]
361    pub fn is_scroll_container(self) -> bool {
362        match self {
363            Self::Visible | Self::Clip => false,
364            Self::Hidden | Self::Scroll => true,
365        }
366    }
367
368    /// Returns `Some(0.0)` if the overflow mode would cause the automatic minimum size of a Flexbox or CSS Grid item
369    /// to be `0`. Else returns None.
370    #[inline(always)]
371    pub(crate) fn maybe_into_automatic_min_size(self) -> Option<f32> {
372        match self.is_scroll_container() {
373            true => Some(0.0),
374            false => None,
375        }
376    }
377}
378
379#[cfg(feature = "parse")]
380crate::util::parse::impl_parse_for_keyword_enum!(Overflow,
381    "visible" => Visible,
382    "hidden" => Hidden,
383    "clip" => Clip,
384    "scroll" => Scroll,
385);
386
387/// Sets the direction of text, table and grid columns, and horizontal overflow.
388/// <https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/direction>
389#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
390#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
391pub enum Direction {
392    #[default]
393    /// Left-to-right
394    Ltr,
395    /// Right-to-left
396    Rtl,
397}
398
399impl Direction {
400    /// Returns true if the direction is right-to-left
401    #[inline]
402    pub(crate) fn is_rtl(&self) -> bool {
403        matches!(self, Direction::Rtl)
404    }
405}
406
407#[cfg(feature = "parse")]
408crate::util::parse::impl_parse_for_keyword_enum!(Direction,
409    "ltr" => Ltr,
410    "rtl" => Rtl,
411);
412
413/// A typed representation of the CSS style information for a single node.
414///
415/// The most important idea in flexbox is the notion of a "main" and "cross" axis, which are always perpendicular to each other.
416/// The orientation of these axes are controlled via the [`FlexDirection`] field of this struct.
417///
418/// This struct follows the [CSS equivalent](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox) directly;
419/// information about the behavior on the web should transfer directly.
420///
421/// Detailed information about the exact behavior of each of these fields
422/// can be found on [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS) by searching for the field name.
423/// The distinction between margin, padding and border is explained well in
424/// this [introduction to the box model](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model).
425///
426/// If the behavior does not match the flexbox layout algorithm on the web, please file a bug!
427#[derive(Clone, PartialEq, Debug)]
428#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
429#[cfg_attr(feature = "serde", serde(default))]
430pub struct Style<S: CheapCloneStr = DefaultCheapStr> {
431    /// This is a dummy field which is necessary to make Taffy compile with the `grid` feature disabled
432    /// It should always be set to `core::marker::PhantomData`.
433    pub dummy: core::marker::PhantomData<S>,
434    /// What layout strategy should be used?
435    pub display: Display,
436    /// Whether a child is display:table or not. This affects children of block layouts.
437    /// This should really be part of `Display`, but it is currently seperate because table layout isn't implemented
438    pub item_is_table: bool,
439    /// Is it a replaced element like an image or form field?
440    /// <https://drafts.csswg.org/css-sizing-3/#min-content-zero>
441    pub item_is_replaced: bool,
442    /// Should size styles apply to the content box or the border box of the node
443    pub box_sizing: BoxSizing,
444    /// Sets the direction of text, table and grid columns, and horizontal overflow.
445    pub direction: Direction,
446
447    // Overflow properties
448    /// How children overflowing their container should affect layout
449    pub overflow: Point<Overflow>,
450    /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes.
451    pub scrollbar_width: f32,
452
453    #[cfg(feature = "float_layout")]
454    /// Should the box be floated
455    pub float: Float,
456    #[cfg(feature = "float_layout")]
457    /// Should the box clear floats
458    pub clear: Clear,
459
460    // Position properties
461    /// What should the `position` value of this struct use as a base offset?
462    pub position: Position,
463    /// How should the position of this element be tweaked relative to the layout defined?
464    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
465    pub inset: Rect<LengthPercentageAuto>,
466
467    // Size properties
468    /// Sets the initial size of the item
469    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
470    pub size: Size<Dimension>,
471    /// Controls the minimum size of the item
472    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
473    pub min_size: Size<Dimension>,
474    /// Controls the maximum size of the item
475    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
476    pub max_size: Size<Dimension>,
477    /// Sets the preferred aspect ratio for the item
478    ///
479    /// The ratio is calculated as width divided by height.
480    pub aspect_ratio: Option<f32>,
481
482    // Spacing Properties
483    /// How large should the margin be on each side?
484    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
485    pub margin: Rect<LengthPercentageAuto>,
486    /// How large should the padding be on each side?
487    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
488    pub padding: Rect<LengthPercentage>,
489    /// How large should the border be on each side?
490    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
491    pub border: Rect<LengthPercentage>,
492
493    // Alignment properties
494    /// How this node's children aligned in the cross/block axis?
495    #[cfg(any(feature = "flexbox", feature = "grid"))]
496    pub align_items: Option<AlignItems>,
497    /// How this node should be aligned in the cross/block axis
498    /// Falls back to the parents [`AlignItems`] if not set
499    #[cfg(any(feature = "flexbox", feature = "grid"))]
500    pub align_self: Option<AlignSelf>,
501    /// How this node's children should be aligned in the inline axis
502    #[cfg(feature = "grid")]
503    pub justify_items: Option<AlignItems>,
504    /// How this node should be aligned in the inline axis
505    /// Falls back to the parents [`JustifyItems`] if not set
506    #[cfg(feature = "grid")]
507    pub justify_self: Option<AlignSelf>,
508    /// How should content contained within this item be aligned in the cross/block axis
509    #[cfg(any(feature = "flexbox", feature = "grid"))]
510    pub align_content: Option<AlignContent>,
511    /// How should content contained within this item be aligned in the main/inline axis
512    #[cfg(any(feature = "flexbox", feature = "grid"))]
513    pub justify_content: Option<JustifyContent>,
514    /// How large should the gaps between items in a grid or flex container be?
515    #[cfg(any(feature = "flexbox", feature = "grid"))]
516    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
517    pub gap: Size<LengthPercentage>,
518
519    // Block container properties
520    /// How items elements should aligned in the inline axis
521    #[cfg(feature = "block_layout")]
522    pub text_align: TextAlign,
523
524    // Flexbox container properties
525    /// Which direction does the main axis flow in?
526    #[cfg(feature = "flexbox")]
527    pub flex_direction: FlexDirection,
528    /// Should elements wrap, or stay in a single line?
529    #[cfg(feature = "flexbox")]
530    pub flex_wrap: FlexWrap,
531
532    // Flexbox item properties
533    /// Sets the initial main axis size of the item
534    #[cfg(feature = "flexbox")]
535    pub flex_basis: Dimension,
536    /// The relative rate at which this item grows when it is expanding to fill space
537    ///
538    /// 0.0 is the default value, and this value must be positive.
539    #[cfg(feature = "flexbox")]
540    pub flex_grow: f32,
541    /// The relative rate at which this item shrinks when it is contracting to fit into space
542    ///
543    /// 1.0 is the default value, and this value must be positive.
544    #[cfg(feature = "flexbox")]
545    pub flex_shrink: f32,
546
547    // Grid container properies
548    /// Defines the track sizing functions (heights) of the grid rows
549    #[cfg(feature = "grid")]
550    pub grid_template_rows: GridTrackVec<GridTemplateComponent<S>>,
551    /// Defines the track sizing functions (widths) of the grid columns
552    #[cfg(feature = "grid")]
553    pub grid_template_columns: GridTrackVec<GridTemplateComponent<S>>,
554    /// Defines the size of implicitly created rows
555    #[cfg(feature = "grid")]
556    pub grid_auto_rows: GridTrackVec<TrackSizingFunction>,
557    /// Defined the size of implicitly created columns
558    #[cfg(feature = "grid")]
559    pub grid_auto_columns: GridTrackVec<TrackSizingFunction>,
560    /// Controls how items get placed into the grid for auto-placed items
561    #[cfg(feature = "grid")]
562    pub grid_auto_flow: GridAutoFlow,
563
564    // Grid container named properties
565    /// Defines the rectangular grid areas
566    #[cfg(feature = "grid")]
567    pub grid_template_areas: GridTrackVec<GridTemplateArea<S>>,
568    /// The named lines between the columns
569    #[cfg(feature = "grid")]
570    pub grid_template_column_names: GridTrackVec<GridTrackVec<S>>,
571    /// The named lines between the rows
572    #[cfg(feature = "grid")]
573    pub grid_template_row_names: GridTrackVec<GridTrackVec<S>>,
574
575    // Grid child properties
576    /// Defines which row in the grid the item should start and end at
577    #[cfg(feature = "grid")]
578    pub grid_row: Line<GridPlacement<S>>,
579    /// Defines which column in the grid the item should start and end at
580    #[cfg(feature = "grid")]
581    pub grid_column: Line<GridPlacement<S>>,
582}
583
584impl<S: CheapCloneStr> Style<S> {
585    /// The [`Default`] layout, in a form that can be used in const functions
586    pub const DEFAULT: Style<S> = Style {
587        dummy: core::marker::PhantomData,
588        display: Display::DEFAULT,
589        item_is_table: false,
590        item_is_replaced: false,
591        box_sizing: BoxSizing::BorderBox,
592        direction: Direction::Ltr,
593        overflow: Point { x: Overflow::Visible, y: Overflow::Visible },
594        scrollbar_width: 0.0,
595        #[cfg(feature = "float_layout")]
596        float: Float::None,
597        #[cfg(feature = "float_layout")]
598        clear: Clear::None,
599        position: Position::Relative,
600        inset: Rect::auto(),
601        margin: Rect::zero(),
602        padding: Rect::zero(),
603        border: Rect::zero(),
604        size: Size::auto(),
605        min_size: Size::auto(),
606        max_size: Size::auto(),
607        aspect_ratio: None,
608        #[cfg(any(feature = "flexbox", feature = "grid"))]
609        gap: Size::zero(),
610        // Alignment
611        #[cfg(any(feature = "flexbox", feature = "grid"))]
612        align_items: None,
613        #[cfg(any(feature = "flexbox", feature = "grid"))]
614        align_self: None,
615        #[cfg(feature = "grid")]
616        justify_items: None,
617        #[cfg(feature = "grid")]
618        justify_self: None,
619        #[cfg(any(feature = "flexbox", feature = "grid"))]
620        align_content: None,
621        #[cfg(any(feature = "flexbox", feature = "grid"))]
622        justify_content: None,
623        // Block
624        #[cfg(feature = "block_layout")]
625        text_align: TextAlign::Auto,
626        // Flexbox
627        #[cfg(feature = "flexbox")]
628        flex_direction: FlexDirection::Row,
629        #[cfg(feature = "flexbox")]
630        flex_wrap: FlexWrap::NoWrap,
631        #[cfg(feature = "flexbox")]
632        flex_grow: 0.0,
633        #[cfg(feature = "flexbox")]
634        flex_shrink: 1.0,
635        #[cfg(feature = "flexbox")]
636        flex_basis: Dimension::AUTO,
637        // Grid
638        #[cfg(feature = "grid")]
639        grid_template_rows: GridTrackVec::new(),
640        #[cfg(feature = "grid")]
641        grid_template_columns: GridTrackVec::new(),
642        #[cfg(feature = "grid")]
643        grid_template_areas: GridTrackVec::new(),
644        #[cfg(feature = "grid")]
645        grid_template_column_names: GridTrackVec::new(),
646        #[cfg(feature = "grid")]
647        grid_template_row_names: GridTrackVec::new(),
648        #[cfg(feature = "grid")]
649        grid_auto_rows: GridTrackVec::new(),
650        #[cfg(feature = "grid")]
651        grid_auto_columns: GridTrackVec::new(),
652        #[cfg(feature = "grid")]
653        grid_auto_flow: GridAutoFlow::Row,
654        #[cfg(feature = "grid")]
655        grid_row: Line { start: GridPlacement::<S>::Auto, end: GridPlacement::<S>::Auto },
656        #[cfg(feature = "grid")]
657        grid_column: Line { start: GridPlacement::<S>::Auto, end: GridPlacement::<S>::Auto },
658    };
659}
660
661impl<S: CheapCloneStr> Default for Style<S> {
662    fn default() -> Self {
663        Style::DEFAULT
664    }
665}
666
667impl<S: CheapCloneStr> CoreStyle for Style<S> {
668    type CustomIdent = S;
669
670    #[inline(always)]
671    fn box_generation_mode(&self) -> BoxGenerationMode {
672        match self.display {
673            Display::None => BoxGenerationMode::None,
674            _ => BoxGenerationMode::Normal,
675        }
676    }
677    #[inline(always)]
678    #[cfg(feature = "block_layout")]
679    fn is_block(&self) -> bool {
680        matches!(self.display, Display::Block)
681    }
682    #[inline(always)]
683    fn is_compressible_replaced(&self) -> bool {
684        self.item_is_replaced
685    }
686    #[inline(always)]
687    fn box_sizing(&self) -> BoxSizing {
688        self.box_sizing
689    }
690    #[inline(always)]
691    fn direction(&self) -> Direction {
692        self.direction
693    }
694    #[inline(always)]
695    fn overflow(&self) -> Point<Overflow> {
696        self.overflow
697    }
698    #[inline(always)]
699    fn scrollbar_width(&self) -> f32 {
700        self.scrollbar_width
701    }
702    #[inline(always)]
703    fn position(&self) -> Position {
704        self.position
705    }
706    #[inline(always)]
707    fn inset(&self) -> Rect<LengthPercentageAuto> {
708        self.inset
709    }
710    #[inline(always)]
711    fn size(&self) -> Size<Dimension> {
712        self.size
713    }
714    #[inline(always)]
715    fn min_size(&self) -> Size<Dimension> {
716        self.min_size
717    }
718    #[inline(always)]
719    fn max_size(&self) -> Size<Dimension> {
720        self.max_size
721    }
722    #[inline(always)]
723    fn aspect_ratio(&self) -> Option<f32> {
724        self.aspect_ratio
725    }
726    #[inline(always)]
727    fn margin(&self) -> Rect<LengthPercentageAuto> {
728        self.margin
729    }
730    #[inline(always)]
731    fn padding(&self) -> Rect<LengthPercentage> {
732        self.padding
733    }
734    #[inline(always)]
735    fn border(&self) -> Rect<LengthPercentage> {
736        self.border
737    }
738}
739
740impl<T: CoreStyle> CoreStyle for &'_ T {
741    type CustomIdent = T::CustomIdent;
742
743    #[inline(always)]
744    fn box_generation_mode(&self) -> BoxGenerationMode {
745        (*self).box_generation_mode()
746    }
747    #[inline(always)]
748    fn is_block(&self) -> bool {
749        (*self).is_block()
750    }
751    #[inline(always)]
752    fn is_compressible_replaced(&self) -> bool {
753        (*self).is_compressible_replaced()
754    }
755    #[inline(always)]
756    fn box_sizing(&self) -> BoxSizing {
757        (*self).box_sizing()
758    }
759    #[inline(always)]
760    fn direction(&self) -> Direction {
761        (*self).direction()
762    }
763    #[inline(always)]
764    fn overflow(&self) -> Point<Overflow> {
765        (*self).overflow()
766    }
767    #[inline(always)]
768    fn scrollbar_width(&self) -> f32 {
769        (*self).scrollbar_width()
770    }
771    #[inline(always)]
772    fn position(&self) -> Position {
773        (*self).position()
774    }
775    #[inline(always)]
776    fn inset(&self) -> Rect<LengthPercentageAuto> {
777        (*self).inset()
778    }
779    #[inline(always)]
780    fn size(&self) -> Size<Dimension> {
781        (*self).size()
782    }
783    #[inline(always)]
784    fn min_size(&self) -> Size<Dimension> {
785        (*self).min_size()
786    }
787    #[inline(always)]
788    fn max_size(&self) -> Size<Dimension> {
789        (*self).max_size()
790    }
791    #[inline(always)]
792    fn aspect_ratio(&self) -> Option<f32> {
793        (*self).aspect_ratio()
794    }
795    #[inline(always)]
796    fn margin(&self) -> Rect<LengthPercentageAuto> {
797        (*self).margin()
798    }
799    #[inline(always)]
800    fn padding(&self) -> Rect<LengthPercentage> {
801        (*self).padding()
802    }
803    #[inline(always)]
804    fn border(&self) -> Rect<LengthPercentage> {
805        (*self).border()
806    }
807}
808
809#[cfg(feature = "block_layout")]
810impl<S: CheapCloneStr> BlockContainerStyle for Style<S> {
811    #[inline(always)]
812    fn text_align(&self) -> TextAlign {
813        self.text_align
814    }
815}
816
817#[cfg(feature = "block_layout")]
818impl<T: BlockContainerStyle> BlockContainerStyle for &'_ T {
819    #[inline(always)]
820    fn text_align(&self) -> TextAlign {
821        (*self).text_align()
822    }
823}
824
825#[cfg(feature = "block_layout")]
826impl<S: CheapCloneStr> BlockItemStyle for Style<S> {
827    #[inline(always)]
828    fn is_table(&self) -> bool {
829        self.item_is_table
830    }
831
832    #[cfg(feature = "float_layout")]
833    #[inline(always)]
834    fn float(&self) -> Float {
835        self.float
836    }
837
838    #[cfg(feature = "float_layout")]
839    #[inline(always)]
840    fn clear(&self) -> Clear {
841        self.clear
842    }
843}
844
845#[cfg(feature = "block_layout")]
846impl<T: BlockItemStyle> BlockItemStyle for &'_ T {
847    #[inline(always)]
848    fn is_table(&self) -> bool {
849        (*self).is_table()
850    }
851
852    #[cfg(feature = "float_layout")]
853    #[inline(always)]
854    fn float(&self) -> Float {
855        (*self).float()
856    }
857
858    #[cfg(feature = "float_layout")]
859    #[inline(always)]
860    fn clear(&self) -> Clear {
861        (*self).clear()
862    }
863}
864
865#[cfg(feature = "flexbox")]
866impl<S: CheapCloneStr> FlexboxContainerStyle for Style<S> {
867    #[inline(always)]
868    fn flex_direction(&self) -> FlexDirection {
869        self.flex_direction
870    }
871    #[inline(always)]
872    fn flex_wrap(&self) -> FlexWrap {
873        self.flex_wrap
874    }
875    #[inline(always)]
876    fn gap(&self) -> Size<LengthPercentage> {
877        self.gap
878    }
879    #[inline(always)]
880    fn align_content(&self) -> Option<AlignContent> {
881        self.align_content
882    }
883    #[inline(always)]
884    fn align_items(&self) -> Option<AlignItems> {
885        self.align_items
886    }
887    #[inline(always)]
888    fn justify_content(&self) -> Option<JustifyContent> {
889        self.justify_content
890    }
891}
892
893#[cfg(feature = "flexbox")]
894impl<T: FlexboxContainerStyle> FlexboxContainerStyle for &'_ T {
895    #[inline(always)]
896    fn flex_direction(&self) -> FlexDirection {
897        (*self).flex_direction()
898    }
899    #[inline(always)]
900    fn flex_wrap(&self) -> FlexWrap {
901        (*self).flex_wrap()
902    }
903    #[inline(always)]
904    fn gap(&self) -> Size<LengthPercentage> {
905        (*self).gap()
906    }
907    #[inline(always)]
908    fn align_content(&self) -> Option<AlignContent> {
909        (*self).align_content()
910    }
911    #[inline(always)]
912    fn align_items(&self) -> Option<AlignItems> {
913        (*self).align_items()
914    }
915    #[inline(always)]
916    fn justify_content(&self) -> Option<JustifyContent> {
917        (*self).justify_content()
918    }
919}
920
921#[cfg(feature = "flexbox")]
922impl<S: CheapCloneStr> FlexboxItemStyle for Style<S> {
923    #[inline(always)]
924    fn flex_basis(&self) -> Dimension {
925        self.flex_basis
926    }
927    #[inline(always)]
928    fn flex_grow(&self) -> f32 {
929        self.flex_grow
930    }
931    #[inline(always)]
932    fn flex_shrink(&self) -> f32 {
933        self.flex_shrink
934    }
935    #[inline(always)]
936    fn align_self(&self) -> Option<AlignSelf> {
937        self.align_self
938    }
939}
940
941#[cfg(feature = "flexbox")]
942impl<T: FlexboxItemStyle> FlexboxItemStyle for &'_ T {
943    #[inline(always)]
944    fn flex_basis(&self) -> Dimension {
945        (*self).flex_basis()
946    }
947    #[inline(always)]
948    fn flex_grow(&self) -> f32 {
949        (*self).flex_grow()
950    }
951    #[inline(always)]
952    fn flex_shrink(&self) -> f32 {
953        (*self).flex_shrink()
954    }
955    #[inline(always)]
956    fn align_self(&self) -> Option<AlignSelf> {
957        (*self).align_self()
958    }
959}
960
961#[cfg(feature = "grid")]
962impl<S: CheapCloneStr> GridContainerStyle for Style<S> {
963    type Repetition<'a>
964        = &'a GridTemplateRepetition<S>
965    where
966        Self: 'a;
967
968    type TemplateTrackList<'a>
969        = core::iter::Map<
970        core::slice::Iter<'a, GridTemplateComponent<S>>,
971        fn(&'a GridTemplateComponent<S>) -> GenericGridTemplateComponent<S, &'a GridTemplateRepetition<S>>,
972    >
973    where
974        Self: 'a;
975
976    type AutoTrackList<'a>
977        = core::iter::Copied<core::slice::Iter<'a, TrackSizingFunction>>
978    where
979        Self: 'a;
980
981    #[cfg(feature = "grid")]
982    type TemplateLineNames<'a>
983        = core::iter::Map<core::slice::Iter<'a, GridTrackVec<S>>, fn(&GridTrackVec<S>) -> core::slice::Iter<'_, S>>
984    where
985        Self: 'a;
986    #[cfg(feature = "grid")]
987    type GridTemplateAreas<'a>
988        = core::iter::Cloned<core::slice::Iter<'a, GridTemplateArea<S>>>
989    where
990        Self: 'a;
991
992    #[inline(always)]
993    fn grid_template_rows(&self) -> Option<Self::TemplateTrackList<'_>> {
994        Some(self.grid_template_rows.iter().map(|c| c.as_component_ref()))
995    }
996    #[inline(always)]
997    fn grid_template_columns(&self) -> Option<Self::TemplateTrackList<'_>> {
998        Some(self.grid_template_columns.iter().map(|c| c.as_component_ref()))
999    }
1000    #[inline(always)]
1001    fn grid_auto_rows(&self) -> Self::AutoTrackList<'_> {
1002        self.grid_auto_rows.iter().copied()
1003    }
1004    #[inline(always)]
1005    fn grid_auto_columns(&self) -> Self::AutoTrackList<'_> {
1006        self.grid_auto_columns.iter().copied()
1007    }
1008    #[inline(always)]
1009    fn grid_auto_flow(&self) -> GridAutoFlow {
1010        self.grid_auto_flow
1011    }
1012    #[inline(always)]
1013    fn gap(&self) -> Size<LengthPercentage> {
1014        self.gap
1015    }
1016    #[inline(always)]
1017    fn align_content(&self) -> Option<AlignContent> {
1018        self.align_content
1019    }
1020    #[inline(always)]
1021    fn justify_content(&self) -> Option<JustifyContent> {
1022        self.justify_content
1023    }
1024    #[inline(always)]
1025    fn align_items(&self) -> Option<AlignItems> {
1026        self.align_items
1027    }
1028    #[inline(always)]
1029    fn justify_items(&self) -> Option<AlignItems> {
1030        self.justify_items
1031    }
1032
1033    #[inline(always)]
1034    #[cfg(feature = "grid")]
1035    fn grid_template_areas(&self) -> Option<Self::GridTemplateAreas<'_>> {
1036        Some(self.grid_template_areas.iter().cloned())
1037    }
1038
1039    #[inline(always)]
1040    #[cfg(feature = "grid")]
1041    fn grid_template_column_names(&self) -> Option<Self::TemplateLineNames<'_>> {
1042        Some(self.grid_template_column_names.iter().map(|names| names.iter()))
1043    }
1044
1045    #[inline(always)]
1046    #[cfg(feature = "grid")]
1047    fn grid_template_row_names(&self) -> Option<Self::TemplateLineNames<'_>> {
1048        Some(self.grid_template_row_names.iter().map(|names| names.iter()))
1049    }
1050}
1051
1052#[cfg(feature = "grid")]
1053impl<T: GridContainerStyle> GridContainerStyle for &'_ T {
1054    type Repetition<'a>
1055        = T::Repetition<'a>
1056    where
1057        Self: 'a;
1058
1059    type TemplateTrackList<'a>
1060        = T::TemplateTrackList<'a>
1061    where
1062        Self: 'a;
1063
1064    type AutoTrackList<'a>
1065        = T::AutoTrackList<'a>
1066    where
1067        Self: 'a;
1068
1069    /// The type returned by grid_template_row_names and grid_template_column_names
1070    #[cfg(feature = "grid")]
1071    type TemplateLineNames<'a>
1072        = T::TemplateLineNames<'a>
1073    where
1074        Self: 'a;
1075    #[cfg(feature = "grid")]
1076    type GridTemplateAreas<'a>
1077        = T::GridTemplateAreas<'a>
1078    where
1079        Self: 'a;
1080
1081    #[inline(always)]
1082    fn grid_template_rows(&self) -> Option<Self::TemplateTrackList<'_>> {
1083        (*self).grid_template_rows()
1084    }
1085    #[inline(always)]
1086    fn grid_template_columns(&self) -> Option<Self::TemplateTrackList<'_>> {
1087        (*self).grid_template_columns()
1088    }
1089    #[inline(always)]
1090    fn grid_auto_rows(&self) -> Self::AutoTrackList<'_> {
1091        (*self).grid_auto_rows()
1092    }
1093    #[inline(always)]
1094    fn grid_auto_columns(&self) -> Self::AutoTrackList<'_> {
1095        (*self).grid_auto_columns()
1096    }
1097    #[cfg(feature = "grid")]
1098    #[inline(always)]
1099    fn grid_template_areas(&self) -> Option<Self::GridTemplateAreas<'_>> {
1100        (*self).grid_template_areas()
1101    }
1102    #[cfg(feature = "grid")]
1103    #[inline(always)]
1104    fn grid_template_column_names(&self) -> Option<Self::TemplateLineNames<'_>> {
1105        (*self).grid_template_column_names()
1106    }
1107    #[cfg(feature = "grid")]
1108    #[inline(always)]
1109    fn grid_template_row_names(&self) -> Option<Self::TemplateLineNames<'_>> {
1110        (*self).grid_template_row_names()
1111    }
1112    #[inline(always)]
1113    fn grid_auto_flow(&self) -> GridAutoFlow {
1114        (*self).grid_auto_flow()
1115    }
1116    #[inline(always)]
1117    fn gap(&self) -> Size<LengthPercentage> {
1118        (*self).gap()
1119    }
1120    #[inline(always)]
1121    fn align_content(&self) -> Option<AlignContent> {
1122        (*self).align_content()
1123    }
1124    #[inline(always)]
1125    fn justify_content(&self) -> Option<JustifyContent> {
1126        (*self).justify_content()
1127    }
1128    #[inline(always)]
1129    fn align_items(&self) -> Option<AlignItems> {
1130        (*self).align_items()
1131    }
1132    #[inline(always)]
1133    fn justify_items(&self) -> Option<AlignItems> {
1134        (*self).justify_items()
1135    }
1136}
1137
1138#[cfg(feature = "grid")]
1139impl<S: CheapCloneStr> GridItemStyle for Style<S> {
1140    #[inline(always)]
1141    fn grid_row(&self) -> Line<GridPlacement<S>> {
1142        // TODO: Investigate eliminating clone
1143        self.grid_row.clone()
1144    }
1145    #[inline(always)]
1146    fn grid_column(&self) -> Line<GridPlacement<S>> {
1147        // TODO: Investigate eliminating clone
1148        self.grid_column.clone()
1149    }
1150    #[inline(always)]
1151    fn align_self(&self) -> Option<AlignSelf> {
1152        self.align_self
1153    }
1154    #[inline(always)]
1155    fn justify_self(&self) -> Option<AlignSelf> {
1156        self.justify_self
1157    }
1158}
1159
1160#[cfg(feature = "grid")]
1161impl<T: GridItemStyle> GridItemStyle for &'_ T {
1162    #[inline(always)]
1163    fn grid_row(&self) -> Line<GridPlacement<Self::CustomIdent>> {
1164        (*self).grid_row()
1165    }
1166    #[inline(always)]
1167    fn grid_column(&self) -> Line<GridPlacement<Self::CustomIdent>> {
1168        (*self).grid_column()
1169    }
1170    #[inline(always)]
1171    fn align_self(&self) -> Option<AlignSelf> {
1172        (*self).align_self()
1173    }
1174    #[inline(always)]
1175    fn justify_self(&self) -> Option<AlignSelf> {
1176        (*self).justify_self()
1177    }
1178}
1179
1180#[cfg(test)]
1181mod tests {
1182    use std::sync::Arc;
1183
1184    use super::Style;
1185    use crate::sys::DefaultCheapStr;
1186    use crate::{geometry::*, style_helpers::TaffyAuto as _};
1187
1188    #[test]
1189    fn defaults_match() {
1190        #[cfg(feature = "grid")]
1191        use super::GridPlacement;
1192
1193        let old_defaults: Style<DefaultCheapStr> = Style {
1194            dummy: core::marker::PhantomData,
1195            display: Default::default(),
1196            item_is_table: false,
1197            item_is_replaced: false,
1198            box_sizing: Default::default(),
1199            #[cfg(feature = "float_layout")]
1200            float: Default::default(),
1201            #[cfg(feature = "float_layout")]
1202            clear: Default::default(),
1203            direction: Default::default(),
1204            overflow: Default::default(),
1205            scrollbar_width: 0.0,
1206            position: Default::default(),
1207            #[cfg(feature = "flexbox")]
1208            flex_direction: Default::default(),
1209            #[cfg(feature = "flexbox")]
1210            flex_wrap: Default::default(),
1211            #[cfg(any(feature = "flexbox", feature = "grid"))]
1212            align_items: Default::default(),
1213            #[cfg(any(feature = "flexbox", feature = "grid"))]
1214            align_self: Default::default(),
1215            #[cfg(feature = "grid")]
1216            justify_items: Default::default(),
1217            #[cfg(feature = "grid")]
1218            justify_self: Default::default(),
1219            #[cfg(any(feature = "flexbox", feature = "grid"))]
1220            align_content: Default::default(),
1221            #[cfg(any(feature = "flexbox", feature = "grid"))]
1222            justify_content: Default::default(),
1223            inset: Rect::auto(),
1224            margin: Rect::zero(),
1225            padding: Rect::zero(),
1226            border: Rect::zero(),
1227            gap: Size::zero(),
1228            #[cfg(feature = "block_layout")]
1229            text_align: Default::default(),
1230            #[cfg(feature = "flexbox")]
1231            flex_grow: 0.0,
1232            #[cfg(feature = "flexbox")]
1233            flex_shrink: 1.0,
1234            #[cfg(feature = "flexbox")]
1235            flex_basis: super::Dimension::AUTO,
1236            size: Size::auto(),
1237            min_size: Size::auto(),
1238            max_size: Size::auto(),
1239            aspect_ratio: Default::default(),
1240            #[cfg(feature = "grid")]
1241            grid_template_rows: Default::default(),
1242            #[cfg(feature = "grid")]
1243            grid_template_columns: Default::default(),
1244            #[cfg(feature = "grid")]
1245            grid_template_row_names: Default::default(),
1246            #[cfg(feature = "grid")]
1247            grid_template_column_names: Default::default(),
1248            #[cfg(feature = "grid")]
1249            grid_template_areas: Default::default(),
1250            #[cfg(feature = "grid")]
1251            grid_auto_rows: Default::default(),
1252            #[cfg(feature = "grid")]
1253            grid_auto_columns: Default::default(),
1254            #[cfg(feature = "grid")]
1255            grid_auto_flow: Default::default(),
1256            #[cfg(feature = "grid")]
1257            grid_row: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
1258            #[cfg(feature = "grid")]
1259            grid_column: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
1260        };
1261
1262        assert_eq!(Style::DEFAULT, Style::<DefaultCheapStr>::default());
1263        assert_eq!(Style::DEFAULT, old_defaults);
1264    }
1265
1266    // NOTE: Please feel free the update the sizes in this test as required. This test is here to prevent unintentional size changes
1267    // and to serve as accurate up-to-date documentation on the sizes.
1268    #[test]
1269    fn style_sizes() {
1270        use super::*;
1271        type S = crate::sys::DefaultCheapStr;
1272
1273        fn assert_type_size<T>(expected_size: usize) {
1274            let name = ::core::any::type_name::<T>();
1275            let name = name.replace("taffy::geometry::", "");
1276            let name = name.replace("taffy::style::dimension::", "");
1277            let name = name.replace("taffy::style::alignment::", "");
1278            let name = name.replace("taffy::style::flex::", "");
1279            let name = name.replace("taffy::style::grid::", "");
1280
1281            assert_eq!(
1282                ::core::mem::size_of::<T>(),
1283                expected_size,
1284                "Expected {} for be {} byte(s) but it was {} byte(s)",
1285                name,
1286                expected_size,
1287                ::core::mem::size_of::<T>(),
1288            );
1289        }
1290
1291        // Display and Position
1292        assert_type_size::<Display>(1);
1293        assert_type_size::<BoxSizing>(1);
1294        assert_type_size::<Position>(1);
1295        assert_type_size::<Overflow>(1);
1296
1297        // Dimensions and aggregations of Dimensions
1298        assert_type_size::<f32>(4);
1299        assert_type_size::<LengthPercentage>(8);
1300        assert_type_size::<LengthPercentageAuto>(8);
1301        assert_type_size::<Dimension>(8);
1302        assert_type_size::<Size<LengthPercentage>>(16);
1303        assert_type_size::<Size<LengthPercentageAuto>>(16);
1304        assert_type_size::<Size<Dimension>>(16);
1305        assert_type_size::<Rect<LengthPercentage>>(32);
1306        assert_type_size::<Rect<LengthPercentageAuto>>(32);
1307        assert_type_size::<Rect<Dimension>>(32);
1308
1309        // Alignment
1310        assert_type_size::<AlignContent>(1);
1311        assert_type_size::<AlignItems>(1);
1312        assert_type_size::<Option<AlignItems>>(1);
1313
1314        // Flexbox Container
1315        assert_type_size::<FlexDirection>(1);
1316        assert_type_size::<FlexWrap>(1);
1317
1318        // CSS Grid Container
1319        assert_type_size::<GridAutoFlow>(1);
1320        assert_type_size::<MinTrackSizingFunction>(8);
1321        assert_type_size::<MaxTrackSizingFunction>(8);
1322        assert_type_size::<TrackSizingFunction>(16);
1323        assert_type_size::<Vec<TrackSizingFunction>>(24);
1324        assert_type_size::<Vec<GridTemplateComponent<S>>>(24);
1325
1326        // String-type dependent (String)
1327        assert_type_size::<GridTemplateComponent<String>>(56);
1328        assert_type_size::<GridPlacement<String>>(32);
1329        assert_type_size::<Line<GridPlacement<String>>>(64);
1330        assert_type_size::<Style<String>>(536);
1331
1332        // String-type dependent (Arc<str>)
1333        assert_type_size::<GridTemplateComponent<Arc<str>>>(56);
1334        assert_type_size::<GridPlacement<Arc<str>>>(24);
1335        assert_type_size::<Line<GridPlacement<Arc<str>>>>(48);
1336        assert_type_size::<Style<Arc<str>>>(504);
1337    }
1338}