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 dimension;
4
5#[cfg(feature = "flexbox")]
6mod flex;
7
8pub use self::alignment::{AlignContent, AlignItems, AlignSelf, JustifyContent, JustifyItems, JustifySelf};
9pub use self::dimension::{AvailableSpace, Dimension, LengthPercentage, LengthPercentageAuto};
10
11#[cfg(feature = "flexbox")]
12pub use self::flex::{FlexDirection, FlexWrap, FlexboxContainerStyle, FlexboxItemStyle};
13
14#[cfg(feature = "grid")]
15mod grid;
16#[cfg(feature = "grid")]
17pub(crate) use self::grid::{GenericGridPlacement, OriginZeroGridPlacement};
18#[cfg(feature = "grid")]
19pub use self::grid::{
20 GridAutoFlow, GridContainerStyle, GridItemStyle, GridPlacement, GridTrackRepetition, MaxTrackSizingFunction,
21 MinTrackSizingFunction, NonRepeatedTrackSizingFunction, TrackSizingFunction,
22};
23use crate::geometry::{Point, Rect, Size};
24
25#[cfg(feature = "grid")]
26use crate::geometry::Line;
27#[cfg(feature = "serde")]
28use crate::style_helpers;
29#[cfg(feature = "grid")]
30use crate::util::sys::GridTrackVec;
31
32/// The core set of styles that are shared between all CSS layout nodes
33///
34/// Note that all methods come with a default implementation which simply returns the default value for that style property
35/// but this is a just a convenience to save on boilerplate for styles that your implementation doesn't support. You will need
36/// to override the default implementation for each style property that your style type actually supports.
37pub trait CoreStyle {
38 /// What layout strategy should be used?
39 // fn display(&self);
40
41 // Overflow properties
42 /// How children overflowing their container should affect layout
43 #[inline(always)]
44 fn overflow(&self) -> Point<Overflow> {
45 Style::DEFAULT.overflow
46 }
47 /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes.
48 #[inline(always)]
49 fn scrollbar_width(&self) -> f32 {
50 0.0
51 }
52
53 // Position properties
54 /// What should the `position` value of this struct use as a base offset?
55 #[inline(always)]
56 fn position(&self) -> Position {
57 Style::DEFAULT.position
58 }
59 /// How should the position of this element be tweaked relative to the layout defined?
60 #[inline(always)]
61 fn inset(&self) -> Rect<LengthPercentageAuto> {
62 Style::DEFAULT.inset
63 }
64
65 // Size properies
66 /// Sets the initial size of the item
67 #[inline(always)]
68 fn size(&self) -> Size<Dimension> {
69 Style::DEFAULT.size
70 }
71 /// Controls the minimum size of the item
72 #[inline(always)]
73 fn min_size(&self) -> Size<Dimension> {
74 Style::DEFAULT.min_size
75 }
76 /// Controls the maximum size of the item
77 #[inline(always)]
78 fn max_size(&self) -> Size<Dimension> {
79 Style::DEFAULT.max_size
80 }
81 /// Sets the preferred aspect ratio for the item
82 /// The ratio is calculated as width divided by height.
83 #[inline(always)]
84 fn aspect_ratio(&self) -> Option<f32> {
85 Style::DEFAULT.aspect_ratio
86 }
87
88 // Spacing Properties
89 /// How large should the margin be on each side?
90 #[inline(always)]
91 fn margin(&self) -> Rect<LengthPercentageAuto> {
92 Style::DEFAULT.margin
93 }
94 /// How large should the padding be on each side?
95 #[inline(always)]
96 fn padding(&self) -> Rect<LengthPercentage> {
97 Style::DEFAULT.padding
98 }
99 /// How large should the border be on each side?
100 #[inline(always)]
101 fn border(&self) -> Rect<LengthPercentage> {
102 Style::DEFAULT.border
103 }
104}
105
106/// Sets the layout used for the children of this node
107///
108/// The default values depends on on which feature flags are enabled. The order of precedence is: Flex, Grid, Block, None.
109#[derive(Copy, Clone, PartialEq, Eq, Debug)]
110#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
111pub enum Display {
112 /// The children will follow the block layout algorithm
113 #[cfg(feature = "block_layout")]
114 Block,
115 /// The children will follow the flexbox layout algorithm
116 #[cfg(feature = "flexbox")]
117 Flex,
118 /// The children will follow the CSS Grid layout algorithm
119 #[cfg(feature = "grid")]
120 Grid,
121 /// The children will not be laid out, and will follow absolute positioning
122 None,
123}
124
125impl Display {
126 /// The default of Display.
127 #[cfg(feature = "flexbox")]
128 pub const DEFAULT: Display = Display::Flex;
129
130 /// The default of Display.
131 #[cfg(all(feature = "grid", not(feature = "flexbox")))]
132 pub const DEFAULT: Display = Display::Grid;
133
134 /// The default of Display.
135 #[cfg(all(feature = "block_layout", not(feature = "flexbox"), not(feature = "grid")))]
136 pub const DEFAULT: Display = Display::Block;
137
138 /// The default of Display.
139 #[cfg(all(not(feature = "flexbox"), not(feature = "grid"), not(feature = "block_layout")))]
140 pub const DEFAULT: Display = Display::None;
141}
142
143impl core::fmt::Display for Display {
144 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
145 match self {
146 Display::None => write!(f, "NONE"),
147 #[cfg(feature = "block_layout")]
148 Display::Block => write!(f, "BLOCK"),
149 #[cfg(feature = "flexbox")]
150 Display::Flex => write!(f, "FLEX"),
151 #[cfg(feature = "grid")]
152 Display::Grid => write!(f, "GRID"),
153 }
154 }
155}
156
157impl Default for Display {
158 fn default() -> Self {
159 Self::DEFAULT
160 }
161}
162
163/// The positioning strategy for this item.
164///
165/// This controls both how the origin is determined for the [`Style::position`] field,
166/// and whether or not the item will be controlled by flexbox's layout algorithm.
167///
168/// WARNING: this enum follows the behavior of [CSS's `position` property](https://developer.mozilla.org/en-US/docs/Web/CSS/position),
169/// which can be unintuitive.
170///
171/// [`Position::Relative`] is the default value, in contrast to the default behavior in CSS.
172#[derive(Copy, Clone, PartialEq, Eq, Debug)]
173#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
174pub enum Position {
175 /// The offset is computed relative to the final position given by the layout algorithm.
176 /// Offsets do not affect the position of any other items; they are effectively a correction factor applied at the end.
177 Relative,
178 /// The offset is computed relative to this item's closest positioned ancestor, if any.
179 /// Otherwise, it is placed relative to the origin.
180 /// No space is created for the item in the page layout, and its size will not be altered.
181 ///
182 /// WARNING: to opt-out of layouting entirely, you must use [`Display::None`] instead on your [`Style`] object.
183 Absolute,
184}
185
186impl Default for Position {
187 fn default() -> Self {
188 Self::Relative
189 }
190}
191
192/// How children overflowing their container should affect layout
193///
194/// In CSS the primary effect of this property is to control whether contents of a parent container that overflow that container should
195/// be displayed anyway, be clipped, or trigger the container to become a scroll container. However it also has secondary effects on layout,
196/// the main ones being:
197///
198/// - The automatic minimum size Flexbox/CSS Grid items with non-`Visible` overflow is `0` rather than being content based
199/// - `Overflow::Scroll` nodes have space in the layout reserved for a scrollbar (width controlled by the `scrollbar_width` property)
200///
201/// In Taffy, we only implement the layout related secondary effects as we are not concerned with drawing/painting. The amount of space reserved for
202/// a scrollbar is controlled by the `scrollbar_width` property. If this is `0` then `Scroll` behaves identically to `Hidden`.
203///
204/// <https://developer.mozilla.org/en-US/docs/Web/CSS/overflow>
205#[derive(Copy, Clone, PartialEq, Eq, Debug, Default)]
206#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
207pub enum Overflow {
208 /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content.
209 /// Content that overflows this node *should* contribute to the scroll region of its parent.
210 #[default]
211 Visible,
212 /// The automatic minimum size of this node as a flexbox/grid item should be based on the size of its content.
213 /// Content that overflows this node should *not* contribute to the scroll region of its parent.
214 Clip,
215 /// The automatic minimum size of this node as a flexbox/grid item should be `0`.
216 /// Content that overflows this node should *not* contribute to the scroll region of its parent.
217 Hidden,
218 /// The automatic minimum size of this node as a flexbox/grid item should be `0`. Additionally, space should be reserved
219 /// for a scrollbar. The amount of space reserved is controlled by the `scrollbar_width` property.
220 /// Content that overflows this node should *not* contribute to the scroll region of its parent.
221 Scroll,
222}
223
224impl Overflow {
225 /// Returns true for overflow modes that contain their contents (`Overflow::Hidden`, `Overflow::Scroll`, `Overflow::Auto`)
226 /// or else false for overflow modes that allow their contains to spill (`Overflow::Visible`).
227 #[inline(always)]
228 pub(crate) fn is_scroll_container(self) -> bool {
229 match self {
230 Self::Visible | Self::Clip => false,
231 Self::Hidden | Self::Scroll => true,
232 }
233 }
234
235 /// Returns `Some(0.0)` if the overflow mode would cause the automatic minimum size of a Flexbox or CSS Grid item
236 /// to be `0`. Else returns None.
237 #[inline(always)]
238 pub(crate) fn maybe_into_automatic_min_size(self) -> Option<f32> {
239 match self.is_scroll_container() {
240 true => Some(0.0),
241 false => None,
242 }
243 }
244}
245
246/// A typed representation of the CSS style information for a single node.
247///
248/// The most important idea in flexbox is the notion of a "main" and "cross" axis, which are always perpendicular to each other.
249/// The orientation of these axes are controlled via the [`FlexDirection`] field of this struct.
250///
251/// This struct follows the [CSS equivalent](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox) directly;
252/// information about the behavior on the web should transfer directly.
253///
254/// Detailed information about the exact behavior of each of these fields
255/// can be found on [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS) by searching for the field name.
256/// The distinction between margin, padding and border is explained well in
257/// this [introduction to the box model](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Introduction_to_the_CSS_box_model).
258///
259/// If the behavior does not match the flexbox layout algorithm on the web, please file a bug!
260#[derive(Clone, PartialEq, Debug)]
261#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
262#[cfg_attr(feature = "serde", serde(default))]
263pub struct Style {
264 /// What layout strategy should be used?
265 pub display: Display,
266
267 // Overflow properties
268 /// How children overflowing their container should affect layout
269 pub overflow: Point<Overflow>,
270 /// How much space (in points) should be reserved for the scrollbars of `Overflow::Scroll` and `Overflow::Auto` nodes.
271 pub scrollbar_width: f32,
272
273 // Position properties
274 /// What should the `position` value of this struct use as a base offset?
275 pub position: Position,
276 /// How should the position of this element be tweaked relative to the layout defined?
277 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
278 pub inset: Rect<LengthPercentageAuto>,
279
280 // Size properties
281 /// Sets the initial size of the item
282 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
283 pub size: Size<Dimension>,
284 /// Controls the minimum size of the item
285 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
286 pub min_size: Size<Dimension>,
287 /// Controls the maximum size of the item
288 #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
289 pub max_size: Size<Dimension>,
290 /// Sets the preferred aspect ratio for the item
291 ///
292 /// The ratio is calculated as width divided by height.
293 pub aspect_ratio: Option<f32>,
294
295 // Spacing Properties
296 /// How large should the margin be on each side?
297 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
298 pub margin: Rect<LengthPercentageAuto>,
299 /// How large should the padding be on each side?
300 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
301 pub padding: Rect<LengthPercentage>,
302 /// How large should the border be on each side?
303 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
304 pub border: Rect<LengthPercentage>,
305
306 // Alignment properties
307 /// How this node's children aligned in the cross/block axis?
308 #[cfg(any(feature = "flexbox", feature = "grid"))]
309 pub align_items: Option<AlignItems>,
310 /// How this node should be aligned in the cross/block axis
311 /// Falls back to the parents [`AlignItems`] if not set
312 #[cfg(any(feature = "flexbox", feature = "grid"))]
313 pub align_self: Option<AlignSelf>,
314 /// How this node's children should be aligned in the inline axis
315 #[cfg(feature = "grid")]
316 pub justify_items: Option<AlignItems>,
317 /// How this node should be aligned in the inline axis
318 /// Falls back to the parents [`JustifyItems`] if not set
319 #[cfg(feature = "grid")]
320 pub justify_self: Option<AlignSelf>,
321 /// How should content contained within this item be aligned in the cross/block axis
322 #[cfg(any(feature = "flexbox", feature = "grid"))]
323 pub align_content: Option<AlignContent>,
324 /// How should contained within this item be aligned in the main/inline axis
325 #[cfg(any(feature = "flexbox", feature = "grid"))]
326 pub justify_content: Option<JustifyContent>,
327 /// How large should the gaps between items in a grid or flex container be?
328 #[cfg(any(feature = "flexbox", feature = "grid"))]
329 #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
330 pub gap: Size<LengthPercentage>,
331
332 // Flexbox properties
333 /// Which direction does the main axis flow in?
334 #[cfg(feature = "flexbox")]
335 pub flex_direction: FlexDirection,
336 /// Should elements wrap, or stay in a single line?
337 #[cfg(feature = "flexbox")]
338 pub flex_wrap: FlexWrap,
339 /// Sets the initial main axis size of the item
340 #[cfg(feature = "flexbox")]
341 pub flex_basis: Dimension,
342 /// The relative rate at which this item grows when it is expanding to fill space
343 ///
344 /// 0.0 is the default value, and this value must be positive.
345 #[cfg(feature = "flexbox")]
346 pub flex_grow: f32,
347 /// The relative rate at which this item shrinks when it is contracting to fit into space
348 ///
349 /// 1.0 is the default value, and this value must be positive.
350 #[cfg(feature = "flexbox")]
351 pub flex_shrink: f32,
352
353 // Grid container properies
354 /// Defines the track sizing functions (heights) of the grid rows
355 #[cfg(feature = "grid")]
356 pub grid_template_rows: GridTrackVec<TrackSizingFunction>,
357 /// Defines the track sizing functions (widths) of the grid columns
358 #[cfg(feature = "grid")]
359 pub grid_template_columns: GridTrackVec<TrackSizingFunction>,
360 /// Defines the size of implicitly created rows
361 #[cfg(feature = "grid")]
362 pub grid_auto_rows: GridTrackVec<NonRepeatedTrackSizingFunction>,
363 /// Defined the size of implicitly created columns
364 #[cfg(feature = "grid")]
365 pub grid_auto_columns: GridTrackVec<NonRepeatedTrackSizingFunction>,
366 /// Controls how items get placed into the grid for auto-placed items
367 #[cfg(feature = "grid")]
368 pub grid_auto_flow: GridAutoFlow,
369
370 // Grid child properties
371 /// Defines which row in the grid the item should start and end at
372 #[cfg(feature = "grid")]
373 pub grid_row: Line<GridPlacement>,
374 /// Defines which column in the grid the item should start and end at
375 #[cfg(feature = "grid")]
376 pub grid_column: Line<GridPlacement>,
377}
378
379impl Style {
380 /// The [`Default`] layout, in a form that can be used in const functions
381 pub const DEFAULT: Style = Style {
382 display: Display::DEFAULT,
383 overflow: Point { x: Overflow::Visible, y: Overflow::Visible },
384 scrollbar_width: 0.0,
385 position: Position::Relative,
386 inset: Rect::auto(),
387 margin: Rect::zero(),
388 padding: Rect::zero(),
389 border: Rect::zero(),
390 size: Size::auto(),
391 min_size: Size::auto(),
392 max_size: Size::auto(),
393 aspect_ratio: None,
394 #[cfg(any(feature = "flexbox", feature = "grid"))]
395 gap: Size::zero(),
396 // Alignment
397 #[cfg(any(feature = "flexbox", feature = "grid"))]
398 align_items: None,
399 #[cfg(any(feature = "flexbox", feature = "grid"))]
400 align_self: None,
401 #[cfg(feature = "grid")]
402 justify_items: None,
403 #[cfg(feature = "grid")]
404 justify_self: None,
405 #[cfg(any(feature = "flexbox", feature = "grid"))]
406 align_content: None,
407 #[cfg(any(feature = "flexbox", feature = "grid"))]
408 justify_content: None,
409 // Flexbox
410 #[cfg(feature = "flexbox")]
411 flex_direction: FlexDirection::Row,
412 #[cfg(feature = "flexbox")]
413 flex_wrap: FlexWrap::NoWrap,
414 #[cfg(feature = "flexbox")]
415 flex_grow: 0.0,
416 #[cfg(feature = "flexbox")]
417 flex_shrink: 1.0,
418 #[cfg(feature = "flexbox")]
419 flex_basis: Dimension::Auto,
420 // Grid
421 #[cfg(feature = "grid")]
422 grid_template_rows: GridTrackVec::new(),
423 #[cfg(feature = "grid")]
424 grid_template_columns: GridTrackVec::new(),
425 #[cfg(feature = "grid")]
426 grid_auto_rows: GridTrackVec::new(),
427 #[cfg(feature = "grid")]
428 grid_auto_columns: GridTrackVec::new(),
429 #[cfg(feature = "grid")]
430 grid_auto_flow: GridAutoFlow::Row,
431 #[cfg(feature = "grid")]
432 grid_row: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
433 #[cfg(feature = "grid")]
434 grid_column: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
435 };
436}
437
438impl Default for Style {
439 fn default() -> Self {
440 Style::DEFAULT
441 }
442}
443
444impl CoreStyle for Style {
445 #[inline(always)]
446 fn overflow(&self) -> Point<Overflow> {
447 self.overflow
448 }
449 #[inline(always)]
450 fn scrollbar_width(&self) -> f32 {
451 self.scrollbar_width
452 }
453 #[inline(always)]
454 fn position(&self) -> Position {
455 self.position
456 }
457 #[inline(always)]
458 fn inset(&self) -> Rect<LengthPercentageAuto> {
459 self.inset
460 }
461 #[inline(always)]
462 fn size(&self) -> Size<Dimension> {
463 self.size
464 }
465 #[inline(always)]
466 fn min_size(&self) -> Size<Dimension> {
467 self.min_size
468 }
469 #[inline(always)]
470 fn max_size(&self) -> Size<Dimension> {
471 self.max_size
472 }
473 #[inline(always)]
474 fn aspect_ratio(&self) -> Option<f32> {
475 self.aspect_ratio
476 }
477 #[inline(always)]
478 fn margin(&self) -> Rect<LengthPercentageAuto> {
479 self.margin
480 }
481 #[inline(always)]
482 fn padding(&self) -> Rect<LengthPercentage> {
483 self.padding
484 }
485 #[inline(always)]
486 fn border(&self) -> Rect<LengthPercentage> {
487 self.border
488 }
489}
490
491#[cfg(feature = "flexbox")]
492impl FlexboxContainerStyle for Style {
493 #[inline(always)]
494 fn flex_direction(&self) -> FlexDirection {
495 self.flex_direction
496 }
497 #[inline(always)]
498 fn flex_wrap(&self) -> FlexWrap {
499 self.flex_wrap
500 }
501 #[inline(always)]
502 fn gap(&self) -> Size<LengthPercentage> {
503 self.gap
504 }
505 #[inline(always)]
506 fn align_content(&self) -> Option<AlignContent> {
507 self.align_content
508 }
509 #[inline(always)]
510 fn align_items(&self) -> Option<AlignItems> {
511 self.align_items
512 }
513 #[inline(always)]
514 fn justify_content(&self) -> Option<JustifyContent> {
515 self.justify_content
516 }
517}
518#[cfg(feature = "flexbox")]
519impl FlexboxItemStyle for Style {
520 #[inline(always)]
521 fn flex_basis(&self) -> Dimension {
522 self.flex_basis
523 }
524 #[inline(always)]
525 fn flex_grow(&self) -> f32 {
526 self.flex_grow
527 }
528 #[inline(always)]
529 fn flex_shrink(&self) -> f32 {
530 self.flex_shrink
531 }
532 #[inline(always)]
533 fn align_self(&self) -> Option<AlignSelf> {
534 self.align_self
535 }
536}
537
538#[cfg(feature = "grid")]
539impl GridContainerStyle for Style {
540 #[inline(always)]
541 fn grid_template_rows(&self) -> &[TrackSizingFunction] {
542 &self.grid_template_rows
543 }
544 #[inline(always)]
545 fn grid_template_columns(&self) -> &[TrackSizingFunction] {
546 &self.grid_template_columns
547 }
548 #[inline(always)]
549 fn grid_auto_rows(&self) -> &[NonRepeatedTrackSizingFunction] {
550 &self.grid_auto_rows
551 }
552 #[inline(always)]
553 fn grid_auto_columns(&self) -> &[NonRepeatedTrackSizingFunction] {
554 &self.grid_auto_columns
555 }
556 #[inline(always)]
557 fn grid_auto_flow(&self) -> GridAutoFlow {
558 self.grid_auto_flow
559 }
560 #[inline(always)]
561 fn gap(&self) -> Size<LengthPercentage> {
562 self.gap
563 }
564 #[inline(always)]
565 fn align_content(&self) -> Option<AlignContent> {
566 self.align_content
567 }
568 #[inline(always)]
569 fn justify_content(&self) -> Option<JustifyContent> {
570 self.justify_content
571 }
572 #[inline(always)]
573 fn align_items(&self) -> Option<AlignItems> {
574 self.align_items
575 }
576 #[inline(always)]
577 fn justify_items(&self) -> Option<AlignItems> {
578 self.justify_items
579 }
580}
581#[cfg(feature = "grid")]
582impl GridItemStyle for Style {
583 #[inline(always)]
584 fn grid_row(&self) -> Line<GridPlacement> {
585 self.grid_row
586 }
587 #[inline(always)]
588 fn grid_column(&self) -> Line<GridPlacement> {
589 self.grid_column
590 }
591 #[inline(always)]
592 fn align_self(&self) -> Option<AlignSelf> {
593 self.align_self
594 }
595 #[inline(always)]
596 fn justify_self(&self) -> Option<AlignSelf> {
597 self.justify_self
598 }
599}
600
601#[cfg(test)]
602mod tests {
603 use super::Style;
604 use crate::geometry::*;
605
606 #[test]
607 fn defaults_match() {
608 #[cfg(feature = "grid")]
609 use super::GridPlacement;
610
611 let old_defaults = Style {
612 display: Default::default(),
613 overflow: Default::default(),
614 scrollbar_width: 0.0,
615 position: Default::default(),
616 #[cfg(feature = "flexbox")]
617 flex_direction: Default::default(),
618 #[cfg(feature = "flexbox")]
619 flex_wrap: Default::default(),
620 #[cfg(any(feature = "flexbox", feature = "grid"))]
621 align_items: Default::default(),
622 #[cfg(any(feature = "flexbox", feature = "grid"))]
623 align_self: Default::default(),
624 #[cfg(feature = "grid")]
625 justify_items: Default::default(),
626 #[cfg(feature = "grid")]
627 justify_self: Default::default(),
628 #[cfg(any(feature = "flexbox", feature = "grid"))]
629 align_content: Default::default(),
630 #[cfg(any(feature = "flexbox", feature = "grid"))]
631 justify_content: Default::default(),
632 inset: Rect::auto(),
633 margin: Rect::zero(),
634 padding: Rect::zero(),
635 border: Rect::zero(),
636 gap: Size::zero(),
637 #[cfg(feature = "flexbox")]
638 flex_grow: 0.0,
639 #[cfg(feature = "flexbox")]
640 flex_shrink: 1.0,
641 #[cfg(feature = "flexbox")]
642 flex_basis: super::Dimension::Auto,
643 size: Size::auto(),
644 min_size: Size::auto(),
645 max_size: Size::auto(),
646 aspect_ratio: Default::default(),
647 #[cfg(feature = "grid")]
648 grid_template_rows: Default::default(),
649 #[cfg(feature = "grid")]
650 grid_template_columns: Default::default(),
651 #[cfg(feature = "grid")]
652 grid_auto_rows: Default::default(),
653 #[cfg(feature = "grid")]
654 grid_auto_columns: Default::default(),
655 #[cfg(feature = "grid")]
656 grid_auto_flow: Default::default(),
657 #[cfg(feature = "grid")]
658 grid_row: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
659 #[cfg(feature = "grid")]
660 grid_column: Line { start: GridPlacement::Auto, end: GridPlacement::Auto },
661 };
662
663 assert_eq!(Style::DEFAULT, Style::default());
664 assert_eq!(Style::DEFAULT, old_defaults);
665 }
666
667 // NOTE: Please feel free the update the sizes in this test as required. This test is here to prevent unintentional size changes
668 // and to serve as accurate up-to-date documentation on the sizes.
669 #[test]
670 fn style_sizes() {
671 use super::*;
672
673 fn assert_type_size<T>(expected_size: usize) {
674 let name = ::core::any::type_name::<T>();
675 let name = name.replace("taffy::geometry::", "");
676 let name = name.replace("taffy::style::dimension::", "");
677 let name = name.replace("taffy::style::alignment::", "");
678 let name = name.replace("taffy::style::flex::", "");
679 let name = name.replace("taffy::style::grid::", "");
680
681 assert_eq!(
682 ::core::mem::size_of::<T>(),
683 expected_size,
684 "Expected {} for be {} byte(s) but it was {} byte(s)",
685 name,
686 expected_size,
687 ::core::mem::size_of::<T>(),
688 );
689 }
690
691 // Display and Position
692 assert_type_size::<Display>(1);
693 assert_type_size::<Position>(1);
694 assert_type_size::<Overflow>(1);
695
696 // Dimensions and aggregations of Dimensions
697 assert_type_size::<f32>(4);
698 assert_type_size::<LengthPercentage>(8);
699 assert_type_size::<LengthPercentageAuto>(8);
700 assert_type_size::<Dimension>(8);
701 assert_type_size::<Size<LengthPercentage>>(16);
702 assert_type_size::<Size<LengthPercentageAuto>>(16);
703 assert_type_size::<Size<Dimension>>(16);
704 assert_type_size::<Rect<LengthPercentage>>(32);
705 assert_type_size::<Rect<LengthPercentageAuto>>(32);
706 assert_type_size::<Rect<Dimension>>(32);
707
708 // Alignment
709 assert_type_size::<AlignContent>(1);
710 assert_type_size::<AlignItems>(1);
711 assert_type_size::<Option<AlignItems>>(1);
712
713 // Flexbox Container
714 assert_type_size::<FlexDirection>(1);
715 assert_type_size::<FlexWrap>(1);
716
717 // CSS Grid Container
718 assert_type_size::<GridAutoFlow>(1);
719 assert_type_size::<MinTrackSizingFunction>(8);
720 assert_type_size::<MaxTrackSizingFunction>(12);
721 assert_type_size::<NonRepeatedTrackSizingFunction>(20);
722 assert_type_size::<TrackSizingFunction>(32);
723 assert_type_size::<Vec<NonRepeatedTrackSizingFunction>>(24);
724 assert_type_size::<Vec<TrackSizingFunction>>(24);
725
726 // CSS Grid Item
727 assert_type_size::<GridPlacement>(4);
728 assert_type_size::<Line<GridPlacement>>(8);
729
730 // Overall
731 assert_type_size::<Style>(352);
732 }
733}