I'm creating a page where I have a parent div which encapsulates multiple child divs from different components in a NextJs project.
I have a preview option where my customers can preview their changes in mobile and desktop view.
I'm able to switch to mobile view using iframe. I want to achieve this without using an iframe.
Even though I change the parent div max width, because the rest of components have sm md lg xl which are taking the values from the view port instead of the parent div I'm unable to solve it.
What should be the approach to solve this?
Media breakpoints allows you to change content appearance based on viewport size. Tailwind's media variants like md:, lg: etc based on them. In order to change content based on parent's size you should use CSS Container Queries. Be aware - they are not production ready - about 75% browser support (actual at December 2022)
Container queries allow us to look at a container size and apply styles to the contents based on the size of their container rather than the viewport or other device characteristics.
Tailwind has official plugin which may help you with it. Install it configure within tailwind.config.js
module.exports = {
plugins: [
require('@tailwindcss/container-queries'),
],
}
You need to add @container class to a parent container and use size modifiers on element you need like @md:bg-blue-500.
<div class="@container max-w-full resize-x overflow-auto">
<div class="p-16 @md:bg-blue-500 bg-amber-400">
Resize me
</div>
</div>
This way element should be yellow unless container size is bigger than 28rem and it will become blue no matter viewport size
Produced CSS is
@container (min-width: 28rem) {
.\@md\:bg-blue-500 {
--tw-bg-opacity: 1;
background-color: rgb(59 130 246 / var(--tw-bg-opacity));
}
}
Check other modifiers here. Please note md:flex and @md:flex are different sizes which may confuse at first
@containers supports labels so you can name containers and specify different CSS for them. Let's say you have reusable component (common situation) you include within loop
<div class="@4xl/aside:bg-red-500 @3xl/primary:bg-yellow-500">
</div>
So within @container/aside element your card will be red after @4xl (56rem) size, while within @container/primary - yellow after @3xl (48rem).
<div class="@container/aside">
<div class="@4xl/aside:bg-red-500 @3xl/primary:bg-yellow-500">
YELLOW
</div>
</div>
<div class="@container/aside">
<div class="@4xl/aside:bg-red-500 @3xl/primary:bg-yellow-500">
RED
</div>
</div>
As I said it's not production ready. The way you want to handle unsupported browsers is up to you. First one - use polyfill. Just add
<script src="https://cdn.jsdelivr.net/npm/container-query-polyfill@1/dist/container-query-polyfill.modern.js"></script>
and it should be enough. However read full docs to improve user experience. I didn't fully tested it myself so cannot guarantee it is 100% solution
Second way is to check does browser supports container queries or not. You can check it via JS
if (!("container" in document.documentElement.style)) {
console.log('No support')
// Do something in that case
}
Another way - via CSS @supports rule
@supports (container-type:inline-size) {
/** Container queries supported */
}
Tailwind has supports: variant for that needs so something like this would work
<div class="supports-[container-type:inline-size]:hidden">
Your browser does not support container queries
Maybe show iframe element as backup (?)
</div>
<div class="supports-[container-type:inline-size]:block hidden">
Here is my cool feature which will be hidden if browser does not supports container queries
</div>
I've created this demo playground without polyfill to check different cases depends on container and window size plus different types of container and browser support
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With