-
I tried to make a responsive column system but it seems that if WIDTH has a MEDIA QUERY and another class of the same element, the latter is also suppressed. Col Component: import * as stylex from "@stylexjs/stylex";
import { col, col_sm, col_md, col_lg, col_xl, col_xxl } from "../design/tokens/flex-grid.stylex";
type Columns = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
type ColProps = {
xs?: Columns;
sm?: Columns;
md?: Columns;
lg?: Columns;
xl?: Columns;
xxl?: Columns;
children: React.ReactNode;
};
export const Col = ({ xs, sm, md, lg, xl, xxl, children }: ColProps) => {
return (
<div {
...stylex.props(
row_styles.rowContent,
xs && col[`_${xs}`],
sm && col_sm[`_${sm}`],
md && col_md[`_${md}`],
lg && col_lg[`_${lg}`],
xl && col_xl[`_${xl}`],
xxl && col_xxl[`_${xxl}`],
)
}>
{children}
</div>
);
};
const row_styles = stylex.create({
row: {
display: 'flex',
flexWrap: 'wrap',
},
rowContent: {
flexShrink: 0,
flex: '0 0 auto',
width:"100%",
maxWidth: "100%",
}
});
export const Row = ({ children }: { children: React.ReactNode }) => {
return (
<div {...stylex.props(row_styles.row)}>
{children}
</div>
);
}; flex-grid.tsx: import * as stylex from "@stylexjs/stylex";
export const breakpoints = {
xs: 0,
sm: 640,
md: 768,
lg: 1024,
xl: 1280,
xxl: 1536,
};
export const width = stylex.defineVars({
_1: '8.33333333%',
_2: '16.66666667%',
_3: '25%',
_4: '33.33333333%',
_5: '41.66666667%',
_6: '50%',
_7: '58.33333333%',
_8: '66.66666667%',
_9: '75%',
_10: '83.33333333%',
_11: '91.66666667%',
_12: '100%',
})
const sm = '@media (min-width: 640px)';
export const col_sm = stylex.create({
_1: { width: { [sm]: width._1 } },
_2: { width: { [sm]: width._2 } },
_3: { width: { [sm]: width._3 } },
_4: { width: { [sm]: width._4 } },
_5: { width: { [sm]: width._5 } },
_6: { width: { [sm]: width._6 } },
_7: { width: { [sm]: width._7 } },
_8: { width: { [sm]: width._8 } },
_9: { width: { [sm]: width._9 } },
_10: { width: { [sm]: width._10 } },
_11: { width: { [sm]: width._11 } },
_12: { width: { [sm]: width._12 } },
});
const md = '@media (min-width: 768px)';
export const col_md = stylex.create({
_1: { width: { [md]: width._1 } },
_2: { width: { [md]: width._2 } },
_3: { width: { [md]: width._3 } },
_4: { width: { [md]: width._4 } },
_5: { width: { [md]: width._5 } },
_6: { width: { [md]: width._6 } },
_7: { width: { [md]: width._7 } },
_8: { width: { [md]: width._8 } },
_9: { width: { [md]: width._9 } },
_10: { width: { [md]: width._10 } },
_11: { width: { [md]: width._11 } },
_12: { width: { [md]: width._12 } },
});
const lg = '@media (min-width: 1024px)';
export const col_lg = stylex.create({
_1: { width: { [lg]: width._1 } },
_2: { width: { [lg]: width._2 } },
_3: { width: { [lg]: width._3 } },
_4: { width: { [lg]: width._4 } },
_5: { width: { [lg]: width._5 } },
_6: { width: { [lg]: width._6 } },
_7: { width: { [lg]: width._7 } },
_8: { width: { [lg]: width._8 } },
_9: { width: { [lg]: width._9 } },
_10: { width: { [lg]: width._10 } },
_11: { width: { [lg]: width._11 } },
_12: { width: { [lg]: width._12 } },
});
const xl = '@media (min-width: 1280px)';
export const col_xl = stylex.create({
_1: { width: { [xl]: width._1 } },
_2: { width: { [xl]: width._2 } },
_3: { width: { [xl]: width._3 } },
_4: { width: { [xl]: width._4 } },
_5: { width: { [xl]: width._5 } },
_6: { width: { [xl]: width._6 } },
_7: { width: { [xl]: width._7 } },
_8: { width: { [xl]: width._8 } },
_9: { width: { [xl]: width._9 } },
_10: { width: { [xl]: width._10 } },
_11: { width: { [xl]: width._11 } },
_12: { width: { [xl]: width._12 } },
});
const xxl = '@media (min-width: 1536px)';
export const col_xxl = stylex.create({
_1: { width: { [xxl]: width._1 } },
_2: { width: { [xxl]: width._2 } },
_3: { width: { [xxl]: width._3 } },
_4: { width: { [xxl]: width._4 } },
_5: { width: { [xxl]: width._5 } },
_6: { width: { [xxl]: width._6 } },
_7: { width: { [xxl]: width._7 } },
_8: { width: { [xxl]: width._8 } },
_9: { width: { [xxl]: width._9 } },
_10: { width: { [xxl]: width._10 } },
_11: { width: { [xxl]: width._11 } },
_12: { width: { [xxl]: width._12 } },
});
export const col = stylex.create({
_1: { width: width._1 },
_2: { width: width._2 },
_3: { width: width._3 },
_4: { width: width._4 },
_5: { width: width._5 },
_6: { width: width._6 },
_7: { width: width._7 },
_8: { width: width._8 },
_9: { width: width._9 },
_10: { width: width._10 },
_11: { width: width._11 },
_12: { width: width._12 },
}); For use: import { Row, Col } from "./col-component.tsx";
<Row>
<Col lg={2}>
<div style={{ width: '100%', height: '50px', background:'green'}}></div>
</Col>
<Col lg={2}>
<div style={{ width: '100%', height: '50px', background:'orange'}}></div>
</Col>
</Row> The problem: Apparently when the MEDIA QUERY (LG) condition is met it works, but once that condition is no longer met the element (COL) has no width and disappears. Any solution? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
I want to start off by saying that such patterns for defining number of columns lead to inconsistencies and the StyleX API was designed specifically to discourage such APIs. Instead of defining the number of columns, a responsive design system to should as for a import * as stylex from "@stylexjs/stylex";
type ColProps = {
children: React.ReactNode;
fluid?: boolean;
style: StyleXStyles<{
flexBasis: number | string;
minWidth?: number | string;
}>;
};
const row_styles = stylex.create({
row: {
display: 'flex',
flexWrap: 'wrap',
},
column: {
flexShrink: 0,
flexBasis: 'auto',
maxWidth: "100%",
},
fluid: {
flexBasis: 0,
flexGrow: 1,
}
});
export const Col = ({ children, fluid = false, style }: ColProps) => {
return (
<div
{...stylex.props(
row_styles.rowContent,
fluid && row_styles.fluid,
style,
)}
>
{children}
</div>
);
};
export const Row = ({ children }: { children: React.ReactNode }) => {
return (
<div {...stylex.props(row_styles.row)}>
{children}
</div>
);
}; Usage: import { Row, Col } from "./col-component.tsx";
const styles = stylex.create({
column: {
minWidth: 360,
}
})
<Row>
<Col fluid style={styles.column}>
<div style={{ width: '100%', height: '50px', background:'green'}}></div>
</Col>
<Col fluid style={styles.column}>
<div style={{ width: '100%', height: '50px', background:'orange'}}></div>
</Col>
</Row> Media queries are a crutch and should be avoided when possible. Specially to keep the total amount of CSS as small as possible. And when media queries are needed, it's more consistent to define all values for a property as single set across different viewport widths. Coming up with arbitrary values for different "media query widths" is an anti-pattern and can result in inconsistent UI that isn't properly responsive. However, if you really want to do what you want, you'd need to use dynamic styles. (In the near future you can have shareable media queries which would be a better API). import * as stylex from "@stylexjs/stylex";
import { width } from "../design/tokens/flex-grid.stylex";
type Columns = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
type Cols = {
xs?: Columns;
sm?: Columns;
md?: Columns;
lg?: Columns;
xl?: Columns;
xxl?: Columns;
}
type ColProps = Cols & {
children: React.ReactNode;
};
export const Col = ({ children, xs = null, sm = xs, md = sm, lg = md, xl = lg, xxl = xl }: ColProps) => {
return (
<div
{...stylex.props(
row_styles.rowContent,
row_styles.columnWidth({xs, sm, md, lg, xl, xxl})
)}
>
{children}
</div>
);
};
// We don't have shareable media queries yet
// But you can make a shared type like `TBreakpoints`
// that can enforce that the same breakpoints are used across your project.
export const breakpoints: TBreakpoints = {
// xs: 0, // default
sm: '@media (min-width: 640px) and (max-width: 767.9px)',
md: '@media (min-width: 768px) and (max-width: 1023.9px)',
lg: '@media (min-width: 1024px) and (max-width: 1279.9px)',
xl: '@media (min-width: 1280px) and (max-width: 1535.9px)',
xxl: '@media (min-width: 1536px)',
};
const row_styles = stylex.create({
row: {
display: 'flex',
flexWrap: 'wrap',
},
rowContent: {
flexShrink: 0,
flex: '0 0 auto',
width: "100%",
maxWidth: "100%",
},
// Each breakpoint defaults to the value of the smaller breakpoint before
// You can change this behaviour as needed.
columnWidth: (cols: Cols) => ({
width: {
default: cols.xs,
[breakpoints.sm]: cols.sm,
[breakpoints.md]: cols.md,
[breakpoints.lg]: cols.lg,
[breakpoints.xl]: cols.xl,
[breakpoints.xxl]: cols.xxl,
}
}),
});
export const Row = ({ children }: { children: React.ReactNode }) => {
return (
<div {...stylex.props(row_styles.row)}>
{children}
</div>
);
}; |
Beta Was this translation helpful? Give feedback.
I want to start off by saying that such patterns for defining number of columns lead to inconsistencies and the StyleX API was designed specifically to discourage such APIs.
Instead of defining the number of columns, a responsive design system to should as for a
min-width
and be fluid automatically.