Support for declarative responsive design
gampleman opened this issue · comments
So far the recommendation for achieving responsive design has been to subscribe to resizes and use an initial size in Elm. While this works, it has some downsides:
- It is unsuitable for static site generators
- It requires flags and JS to set up properly
- It requires the width to be passed into every view, necessitating some plumbing
- It requires re-evaluating the view when resizes happen, which may make it perform poorly
The upside is of course some conceptual simplicity. However I wonder if we could achieve something quite nice with some symbolic operators. We already specify things in Length
values, so some things could be specified as special Length
values:
viewportWidth |> minus (px 30)
which could be compiled to:
calc(100vw - 30px)
However, I'm not sure this would be useful. However, I think we could also provide some responsive layout primitives:
rowIf (viewportWidth |> greaterThan (px 600)) attrs children
which could be compiled to:
.el23 { flex-direction: column; }
@media (width > 600px) { .el23 { flex-direction: row; } }
similarly one could have hiddenIf
. These kinds of techniques could also work for responsive text size.
Finally worth noting that this wouldn't remove the previous technique, but for many usecases it could make it unnecessary.
Also see #16 for some further ideas on this.
I quite like the https://chakra-ui.com/docs/features/responsive-styles approach:
<>
<Box
height={{
base: "100%", // 0-48em
md: "50%", // 48em-80em,
xl: "25%", // 80em+
}}
bg="teal.400"
width={[
"100%", // 0-30em
"50%", // 30em-48em
"25%", // 48em-62em
"15%", // 62em+
]}
/>
{/* responsive font size */}
<Box fontSize={["sm", "md", "lg", "xl"]}>Font Size</Box>
{/* responsive margin */}
<Box mt={[2, 4, 6, 8]} width="full" height="24px" bg="tomato" />
{/* responsive padding */}
<Box bg="papayawhip" p={[2, 4, 6, 8]}>
Padding
</Box>
</>
Every style can be given an object or array and the style that matches the breakpoint size will be used.