1use super::align::{
4 AlignContent, AlignItems, AlignSelf, ContentDistribution, ContentPosition, JustifyContent, SelfPosition,
5};
6use super::{Property, PropertyId};
7use crate::context::PropertyHandlerContext;
8use crate::declaration::{DeclarationBlock, DeclarationList};
9use crate::error::{ParserError, PrinterError};
10use crate::macros::*;
11use crate::prefixes::{is_flex_2009, Feature};
12use crate::printer::Printer;
13use crate::traits::{FromStandard, Parse, PropertyHandler, Shorthand, ToCss, Zero};
14use crate::values::number::{CSSInteger, CSSNumber};
15use crate::values::{
16 length::{LengthPercentage, LengthPercentageOrAuto},
17 percentage::Percentage,
18};
19use crate::vendor_prefix::VendorPrefix;
20#[cfg(feature = "visitor")]
21use crate::visitor::Visit;
22use cssparser::*;
23
24enum_property! {
25 pub enum FlexDirection {
27 Row,
29 RowReverse,
31 Column,
33 ColumnReverse,
35 }
36}
37
38impl Default for FlexDirection {
39 fn default() -> FlexDirection {
40 FlexDirection::Row
41 }
42}
43
44enum_property! {
45 pub enum FlexWrap {
47 "nowrap": NoWrap,
49 "wrap": Wrap,
51 "wrap-reverse": WrapReverse,
53 }
54}
55
56impl Default for FlexWrap {
57 fn default() -> FlexWrap {
58 FlexWrap::NoWrap
59 }
60}
61
62impl FromStandard<FlexWrap> for FlexWrap {
63 fn from_standard(wrap: &FlexWrap) -> Option<FlexWrap> {
64 Some(wrap.clone())
65 }
66}
67
68define_shorthand! {
69 pub struct FlexFlow(VendorPrefix) {
71 direction: FlexDirection(FlexDirection, VendorPrefix),
73 wrap: FlexWrap(FlexWrap, VendorPrefix),
75 }
76}
77
78impl<'i> Parse<'i> for FlexFlow {
79 fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> {
80 let mut direction = None;
81 let mut wrap = None;
82 loop {
83 if direction.is_none() {
84 if let Ok(value) = input.try_parse(FlexDirection::parse) {
85 direction = Some(value);
86 continue;
87 }
88 }
89 if wrap.is_none() {
90 if let Ok(value) = input.try_parse(FlexWrap::parse) {
91 wrap = Some(value);
92 continue;
93 }
94 }
95 break;
96 }
97
98 Ok(FlexFlow {
99 direction: direction.unwrap_or_default(),
100 wrap: wrap.unwrap_or_default(),
101 })
102 }
103}
104
105impl ToCss for FlexFlow {
106 fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
107 where
108 W: std::fmt::Write,
109 {
110 let mut needs_space = false;
111 if self.direction != FlexDirection::default() || self.wrap == FlexWrap::default() {
112 self.direction.to_css(dest)?;
113 needs_space = true;
114 }
115
116 if self.wrap != FlexWrap::default() {
117 if needs_space {
118 dest.write_str(" ")?;
119 }
120 self.wrap.to_css(dest)?;
121 }
122
123 Ok(())
124 }
125}
126
127define_shorthand! {
128pub struct Flex(VendorPrefix) {
130 grow: FlexGrow(CSSNumber, VendorPrefix),
132 shrink: FlexShrink(CSSNumber, VendorPrefix),
134 basis: FlexBasis(LengthPercentageOrAuto, VendorPrefix),
136 }
137}
138
139impl<'i> Parse<'i> for Flex {
140 fn parse<'t>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i, ParserError<'i>>> {
141 if input.try_parse(|input| input.expect_ident_matching("none")).is_ok() {
142 return Ok(Flex {
143 grow: 0.0,
144 shrink: 0.0,
145 basis: LengthPercentageOrAuto::Auto,
146 });
147 }
148
149 let mut grow = None;
150 let mut shrink = None;
151 let mut basis = None;
152
153 loop {
154 if grow.is_none() {
155 if let Ok(val) = input.try_parse(CSSNumber::parse) {
156 grow = Some(val);
157 shrink = input.try_parse(CSSNumber::parse).ok();
158 continue;
159 }
160 }
161
162 if basis.is_none() {
163 if let Ok(val) = input.try_parse(LengthPercentageOrAuto::parse) {
164 basis = Some(val);
165 continue;
166 }
167 }
168
169 break;
170 }
171
172 Ok(Flex {
173 grow: grow.unwrap_or(1.0),
174 shrink: shrink.unwrap_or(1.0),
175 basis: basis.unwrap_or(LengthPercentageOrAuto::LengthPercentage(LengthPercentage::Percentage(
176 Percentage(0.0),
177 ))),
178 })
179 }
180}
181
182impl ToCss for Flex {
183 fn to_css<W>(&self, dest: &mut Printer<W>) -> Result<(), PrinterError>
184 where
185 W: std::fmt::Write,
186 {
187 if self.grow == 0.0 && self.shrink == 0.0 && self.basis == LengthPercentageOrAuto::Auto {
188 dest.write_str("none")?;
189 return Ok(());
190 }
191
192 #[derive(PartialEq)]
193 enum ZeroKind {
194 NonZero,
195 Length,
196 Percentage,
197 }
198
199 let basis_kind = match &self.basis {
202 LengthPercentageOrAuto::LengthPercentage(lp) => match lp {
203 LengthPercentage::Dimension(l) if l.is_zero() => ZeroKind::Length,
204 LengthPercentage::Percentage(p) if p.is_zero() => ZeroKind::Percentage,
205 _ => ZeroKind::NonZero,
206 },
207 _ => ZeroKind::NonZero,
208 };
209
210 if self.grow != 1.0 || self.shrink != 1.0 || basis_kind != ZeroKind::NonZero {
211 self.grow.to_css(dest)?;
212 if self.shrink != 1.0 || basis_kind == ZeroKind::Length {
213 dest.write_str(" ")?;
214 self.shrink.to_css(dest)?;
215 }
216 }
217
218 if basis_kind != ZeroKind::Percentage {
219 if self.grow != 1.0 || self.shrink != 1.0 || basis_kind == ZeroKind::Length {
220 dest.write_str(" ")?;
221 }
222 self.basis.to_css(dest)?;
223 }
224
225 Ok(())
226 }
227}
228
229enum_property! {
232 pub enum BoxOrient {
235 Horizontal,
237 Vertical,
239 InlineAxis,
241 BlockAxis,
243 }
244}
245
246impl FlexDirection {
247 fn to_2009(&self) -> (BoxOrient, BoxDirection) {
248 match self {
249 FlexDirection::Row => (BoxOrient::Horizontal, BoxDirection::Normal),
250 FlexDirection::Column => (BoxOrient::Vertical, BoxDirection::Normal),
251 FlexDirection::RowReverse => (BoxOrient::Horizontal, BoxDirection::Reverse),
252 FlexDirection::ColumnReverse => (BoxOrient::Vertical, BoxDirection::Reverse),
253 }
254 }
255}
256
257enum_property! {
258 pub enum BoxDirection {
261 Normal,
263 Reverse,
265 }
266}
267
268enum_property! {
269 pub enum BoxAlign {
272 Start,
274 End,
276 Center,
278 Baseline,
280 Stretch,
282 }
283}
284
285impl FromStandard<AlignItems> for BoxAlign {
286 fn from_standard(align: &AlignItems) -> Option<BoxAlign> {
287 match align {
288 AlignItems::SelfPosition { overflow: None, value } => match value {
289 SelfPosition::Start | SelfPosition::FlexStart => Some(BoxAlign::Start),
290 SelfPosition::End | SelfPosition::FlexEnd => Some(BoxAlign::End),
291 SelfPosition::Center => Some(BoxAlign::Center),
292 _ => None,
293 },
294 AlignItems::Stretch => Some(BoxAlign::Stretch),
295 _ => None,
296 }
297 }
298}
299
300enum_property! {
301 pub enum BoxPack {
304 Start,
306 End,
308 Center,
310 Justify,
312 }
313}
314
315impl FromStandard<JustifyContent> for BoxPack {
316 fn from_standard(justify: &JustifyContent) -> Option<BoxPack> {
317 match justify {
318 JustifyContent::ContentDistribution(cd) => match cd {
319 ContentDistribution::SpaceBetween => Some(BoxPack::Justify),
320 _ => None,
321 },
322 JustifyContent::ContentPosition { overflow: None, value } => match value {
323 ContentPosition::Start | ContentPosition::FlexStart => Some(BoxPack::Start),
324 ContentPosition::End | ContentPosition::FlexEnd => Some(BoxPack::End),
325 ContentPosition::Center => Some(BoxPack::Center),
326 },
327 _ => None,
328 }
329 }
330}
331
332enum_property! {
333 pub enum BoxLines {
336 Single,
338 Multiple,
340 }
341}
342
343impl FromStandard<FlexWrap> for BoxLines {
344 fn from_standard(wrap: &FlexWrap) -> Option<BoxLines> {
345 match wrap {
346 FlexWrap::NoWrap => Some(BoxLines::Single),
347 FlexWrap::Wrap => Some(BoxLines::Multiple),
348 _ => None,
349 }
350 }
351}
352
353type BoxOrdinalGroup = CSSInteger;
354impl FromStandard<CSSInteger> for BoxOrdinalGroup {
355 fn from_standard(order: &CSSInteger) -> Option<BoxOrdinalGroup> {
356 Some(*order)
357 }
358}
359
360enum_property! {
363 pub enum FlexPack {
366 Start,
368 End,
370 Center,
372 Justify,
374 Distribute,
376 }
377}
378
379impl FromStandard<JustifyContent> for FlexPack {
380 fn from_standard(justify: &JustifyContent) -> Option<FlexPack> {
381 match justify {
382 JustifyContent::ContentDistribution(cd) => match cd {
383 ContentDistribution::SpaceBetween => Some(FlexPack::Justify),
384 ContentDistribution::SpaceAround => Some(FlexPack::Distribute),
385 _ => None,
386 },
387 JustifyContent::ContentPosition { overflow: None, value } => match value {
388 ContentPosition::Start | ContentPosition::FlexStart => Some(FlexPack::Start),
389 ContentPosition::End | ContentPosition::FlexEnd => Some(FlexPack::End),
390 ContentPosition::Center => Some(FlexPack::Center),
391 },
392 _ => None,
393 }
394 }
395}
396
397pub type FlexAlign = BoxAlign;
399
400enum_property! {
401 pub enum FlexItemAlign {
404 Auto,
406 Start,
408 End,
410 Center,
412 Baseline,
414 Stretch,
416 }
417}
418
419impl FromStandard<AlignSelf> for FlexItemAlign {
420 fn from_standard(justify: &AlignSelf) -> Option<FlexItemAlign> {
421 match justify {
422 AlignSelf::Auto => Some(FlexItemAlign::Auto),
423 AlignSelf::Stretch => Some(FlexItemAlign::Stretch),
424 AlignSelf::SelfPosition { overflow: None, value } => match value {
425 SelfPosition::Start | SelfPosition::FlexStart => Some(FlexItemAlign::Start),
426 SelfPosition::End | SelfPosition::FlexEnd => Some(FlexItemAlign::End),
427 SelfPosition::Center => Some(FlexItemAlign::Center),
428 _ => None,
429 },
430 _ => None,
431 }
432 }
433}
434
435enum_property! {
436 pub enum FlexLinePack {
439 Start,
441 End,
443 Center,
445 Justify,
447 Distribute,
449 Stretch,
451 }
452}
453
454impl FromStandard<AlignContent> for FlexLinePack {
455 fn from_standard(justify: &AlignContent) -> Option<FlexLinePack> {
456 match justify {
457 AlignContent::ContentDistribution(cd) => match cd {
458 ContentDistribution::SpaceBetween => Some(FlexLinePack::Justify),
459 ContentDistribution::SpaceAround => Some(FlexLinePack::Distribute),
460 ContentDistribution::Stretch => Some(FlexLinePack::Stretch),
461 _ => None,
462 },
463 AlignContent::ContentPosition { overflow: None, value } => match value {
464 ContentPosition::Start | ContentPosition::FlexStart => Some(FlexLinePack::Start),
465 ContentPosition::End | ContentPosition::FlexEnd => Some(FlexLinePack::End),
466 ContentPosition::Center => Some(FlexLinePack::Center),
467 },
468 _ => None,
469 }
470 }
471}
472
473#[derive(Default, Debug)]
474pub(crate) struct FlexHandler {
475 direction: Option<(FlexDirection, VendorPrefix)>,
476 box_orient: Option<(BoxOrient, VendorPrefix)>,
477 box_direction: Option<(BoxDirection, VendorPrefix)>,
478 wrap: Option<(FlexWrap, VendorPrefix)>,
479 box_lines: Option<(BoxLines, VendorPrefix)>,
480 grow: Option<(CSSNumber, VendorPrefix)>,
481 box_flex: Option<(CSSNumber, VendorPrefix)>,
482 flex_positive: Option<(CSSNumber, VendorPrefix)>,
483 shrink: Option<(CSSNumber, VendorPrefix)>,
484 flex_negative: Option<(CSSNumber, VendorPrefix)>,
485 basis: Option<(LengthPercentageOrAuto, VendorPrefix)>,
486 preferred_size: Option<(LengthPercentageOrAuto, VendorPrefix)>,
487 order: Option<(CSSInteger, VendorPrefix)>,
488 box_ordinal_group: Option<(BoxOrdinalGroup, VendorPrefix)>,
489 flex_order: Option<(CSSInteger, VendorPrefix)>,
490 has_any: bool,
491}
492
493impl<'i> PropertyHandler<'i> for FlexHandler {
494 fn handle_property(
495 &mut self,
496 property: &Property<'i>,
497 dest: &mut DeclarationList<'i>,
498 context: &mut PropertyHandlerContext<'i, '_>,
499 ) -> bool {
500 use Property::*;
501
502 macro_rules! maybe_flush {
503 ($prop: ident, $val: expr, $vp: ident) => {{
504 if let Some((val, prefixes)) = &self.$prop {
507 if val != $val && !prefixes.contains(*$vp) {
508 self.flush(dest, context);
509 }
510 }
511 }};
512 }
513
514 macro_rules! property {
515 ($prop: ident, $val: expr, $vp: ident) => {{
516 maybe_flush!($prop, $val, $vp);
517
518 if let Some((val, prefixes)) = &mut self.$prop {
520 *val = $val.clone();
521 *prefixes |= *$vp;
522 } else {
523 self.$prop = Some(($val.clone(), *$vp));
524 self.has_any = true;
525 }
526 }};
527 }
528
529 match property {
530 FlexDirection(val, vp) => {
531 if context.targets.browsers.is_some() {
532 self.box_direction = None;
533 self.box_orient = None;
534 }
535 property!(direction, val, vp);
536 }
537 BoxOrient(val, vp) => property!(box_orient, val, vp),
538 BoxDirection(val, vp) => property!(box_direction, val, vp),
539 FlexWrap(val, vp) => {
540 if context.targets.browsers.is_some() {
541 self.box_lines = None;
542 }
543 property!(wrap, val, vp);
544 }
545 BoxLines(val, vp) => property!(box_lines, val, vp),
546 FlexFlow(val, vp) => {
547 if context.targets.browsers.is_some() {
548 self.box_direction = None;
549 self.box_orient = None;
550 }
551 property!(direction, &val.direction, vp);
552 property!(wrap, &val.wrap, vp);
553 }
554 FlexGrow(val, vp) => {
555 if context.targets.browsers.is_some() {
556 self.box_flex = None;
557 self.flex_positive = None;
558 }
559 property!(grow, val, vp);
560 }
561 BoxFlex(val, vp) => property!(box_flex, val, vp),
562 FlexPositive(val, vp) => property!(flex_positive, val, vp),
563 FlexShrink(val, vp) => {
564 if context.targets.browsers.is_some() {
565 self.flex_negative = None;
566 }
567 property!(shrink, val, vp);
568 }
569 FlexNegative(val, vp) => property!(flex_negative, val, vp),
570 FlexBasis(val, vp) => {
571 if context.targets.browsers.is_some() {
572 self.preferred_size = None;
573 }
574 property!(basis, val, vp);
575 }
576 FlexPreferredSize(val, vp) => property!(preferred_size, val, vp),
577 Flex(val, vp) => {
578 if context.targets.browsers.is_some() {
579 self.box_flex = None;
580 self.flex_positive = None;
581 self.flex_negative = None;
582 self.preferred_size = None;
583 }
584 maybe_flush!(grow, &val.grow, vp);
585 maybe_flush!(shrink, &val.shrink, vp);
586 maybe_flush!(basis, &val.basis, vp);
587 property!(grow, &val.grow, vp);
588 property!(shrink, &val.shrink, vp);
589 property!(basis, &val.basis, vp);
590 }
591 Order(val, vp) => {
592 if context.targets.browsers.is_some() {
593 self.box_ordinal_group = None;
594 self.flex_order = None;
595 }
596 property!(order, val, vp);
597 }
598 BoxOrdinalGroup(val, vp) => property!(box_ordinal_group, val, vp),
599 FlexOrder(val, vp) => property!(flex_order, val, vp),
600 Unparsed(val) if is_flex_property(&val.property_id) => {
601 self.flush(dest, context);
602 dest.push(property.clone()) }
604 _ => return false,
605 }
606
607 true
608 }
609
610 fn finalize(&mut self, dest: &mut DeclarationList<'i>, context: &mut PropertyHandlerContext<'i, '_>) {
611 self.flush(dest, context);
612 }
613}
614
615impl FlexHandler {
616 fn flush<'i>(&mut self, dest: &mut DeclarationList<'i>, context: &mut PropertyHandlerContext<'i, '_>) {
617 if !self.has_any {
618 return;
619 }
620
621 self.has_any = false;
622
623 let mut direction = std::mem::take(&mut self.direction);
624 let mut wrap = std::mem::take(&mut self.wrap);
625 let mut grow = std::mem::take(&mut self.grow);
626 let mut shrink = std::mem::take(&mut self.shrink);
627 let mut basis = std::mem::take(&mut self.basis);
628 let box_orient = std::mem::take(&mut self.box_orient);
629 let box_direction = std::mem::take(&mut self.box_direction);
630 let box_flex = std::mem::take(&mut self.box_flex);
631 let box_ordinal_group = std::mem::take(&mut self.box_ordinal_group);
632 let box_lines = std::mem::take(&mut self.box_lines);
633 let flex_positive = std::mem::take(&mut self.flex_positive);
634 let flex_negative = std::mem::take(&mut self.flex_negative);
635 let preferred_size = std::mem::take(&mut self.preferred_size);
636 let order = std::mem::take(&mut self.order);
637 let flex_order = std::mem::take(&mut self.flex_order);
638
639 macro_rules! single_property {
640 ($prop: ident, $key: ident $(, 2012: $prop_2012: ident )? $(, 2009: $prop_2009: ident )?) => {
641 if let Some((val, prefix)) = $key {
642 if !prefix.is_empty() {
643 let mut prefix = context.targets.prefixes(prefix, Feature::$prop);
644 if prefix.contains(VendorPrefix::None) {
645 $(
646 if let Some(targets) = context.targets.browsers {
648 let mut prefixes_2009 = VendorPrefix::empty();
649 if is_flex_2009(targets) {
650 prefixes_2009 |= VendorPrefix::WebKit;
651 }
652 if prefix.contains(VendorPrefix::Moz) {
653 prefixes_2009 |= VendorPrefix::Moz;
654 }
655 if !prefixes_2009.is_empty() {
656 if let Some(v) = $prop_2009::from_standard(&val) {
657 dest.push(Property::$prop_2009(v, prefixes_2009));
658 }
659 }
660 }
661 )?
662 }
663
664 $(
665 let mut ms = true;
666 if prefix.contains(VendorPrefix::Ms) {
667 dest.push(Property::$prop_2012(val.clone(), VendorPrefix::Ms));
668 ms = false;
669 }
670 if !ms {
671 prefix.remove(VendorPrefix::Ms);
672 }
673 )?
674
675 prefix.remove(VendorPrefix::Moz);
677 dest.push(Property::$prop(val, prefix))
678 }
679 }
680 };
681 }
682
683 macro_rules! legacy_property {
684 ($prop: ident, $key: expr) => {
685 if let Some((val, prefix)) = $key {
686 if !prefix.is_empty() {
687 dest.push(Property::$prop(val, prefix))
688 }
689 }
690 };
691 }
692
693 legacy_property!(BoxOrient, box_orient);
695 legacy_property!(BoxDirection, box_direction);
696 legacy_property!(BoxOrdinalGroup, box_ordinal_group);
697 legacy_property!(BoxFlex, box_flex);
698 legacy_property!(BoxLines, box_lines);
699 legacy_property!(FlexPositive, flex_positive);
700 legacy_property!(FlexNegative, flex_negative);
701 legacy_property!(FlexPreferredSize, preferred_size.clone());
702 legacy_property!(FlexOrder, flex_order.clone());
703
704 if let Some((direction, _)) = direction {
705 if let Some(targets) = context.targets.browsers {
706 let prefixes = context.targets.prefixes(VendorPrefix::None, Feature::FlexDirection);
707 let mut prefixes_2009 = VendorPrefix::empty();
708 if is_flex_2009(targets) {
709 prefixes_2009 |= VendorPrefix::WebKit;
710 }
711 if prefixes.contains(VendorPrefix::Moz) {
712 prefixes_2009 |= VendorPrefix::Moz;
713 }
714 if !prefixes_2009.is_empty() {
715 let (orient, dir) = direction.to_2009();
716 dest.push(Property::BoxOrient(orient, prefixes_2009));
717 dest.push(Property::BoxDirection(dir, prefixes_2009));
718 }
719 }
720 }
721
722 if let (Some((direction, dir_prefix)), Some((wrap, wrap_prefix))) = (&mut direction, &mut wrap) {
723 let intersection = *dir_prefix & *wrap_prefix;
724 if !intersection.is_empty() {
725 let mut prefix = context.targets.prefixes(intersection, Feature::FlexFlow);
726 prefix.remove(VendorPrefix::Moz);
728 dest.push(Property::FlexFlow(
729 FlexFlow {
730 direction: *direction,
731 wrap: *wrap,
732 },
733 prefix,
734 ));
735 dir_prefix.remove(intersection);
736 wrap_prefix.remove(intersection);
737 }
738 }
739
740 single_property!(FlexDirection, direction);
741 single_property!(FlexWrap, wrap, 2009: BoxLines);
742
743 if let Some(targets) = context.targets.browsers {
744 if let Some((grow, _)) = grow {
745 let prefixes = context.targets.prefixes(VendorPrefix::None, Feature::FlexGrow);
746 let mut prefixes_2009 = VendorPrefix::empty();
747 if is_flex_2009(targets) {
748 prefixes_2009 |= VendorPrefix::WebKit;
749 }
750 if prefixes.contains(VendorPrefix::Moz) {
751 prefixes_2009 |= VendorPrefix::Moz;
752 }
753 if !prefixes_2009.is_empty() {
754 dest.push(Property::BoxFlex(grow, prefixes_2009));
755 }
756 }
757 }
758
759 if let (Some((grow, grow_prefix)), Some((shrink, shrink_prefix)), Some((basis, basis_prefix))) =
760 (&mut grow, &mut shrink, &mut basis)
761 {
762 let intersection = *grow_prefix & *shrink_prefix & *basis_prefix;
763 if !intersection.is_empty() {
764 let mut prefix = context.targets.prefixes(intersection, Feature::Flex);
765 prefix.remove(VendorPrefix::Moz);
767 dest.push(Property::Flex(
768 Flex {
769 grow: *grow,
770 shrink: *shrink,
771 basis: basis.clone(),
772 },
773 prefix,
774 ));
775 grow_prefix.remove(intersection);
776 shrink_prefix.remove(intersection);
777 basis_prefix.remove(intersection);
778 }
779 }
780
781 single_property!(FlexGrow, grow, 2012: FlexPositive);
782 single_property!(FlexShrink, shrink, 2012: FlexNegative);
783 single_property!(FlexBasis, basis, 2012: FlexPreferredSize);
784 single_property!(Order, order, 2012: FlexOrder, 2009: BoxOrdinalGroup);
785 }
786}
787
788#[inline]
789fn is_flex_property(property_id: &PropertyId) -> bool {
790 match property_id {
791 PropertyId::FlexDirection(_)
792 | PropertyId::BoxOrient(_)
793 | PropertyId::BoxDirection(_)
794 | PropertyId::FlexWrap(_)
795 | PropertyId::BoxLines(_)
796 | PropertyId::FlexFlow(_)
797 | PropertyId::FlexGrow(_)
798 | PropertyId::BoxFlex(_)
799 | PropertyId::FlexPositive(_)
800 | PropertyId::FlexShrink(_)
801 | PropertyId::FlexNegative(_)
802 | PropertyId::FlexBasis(_)
803 | PropertyId::FlexPreferredSize(_)
804 | PropertyId::Flex(_)
805 | PropertyId::Order(_)
806 | PropertyId::BoxOrdinalGroup(_)
807 | PropertyId::FlexOrder(_) => true,
808 _ => false,
809 }
810}