Set next/height full - next.js

I have a parent div holding two child div (on with a pic, the other one with text). On screens larger than 768px, the two div are displayed next to each other and the div holding the image will take the whole height defined by the content of the other div. This is working as both child div have a set with: 50%.
On screens smaller than 768px the two div should be stacked on on top of the other. I don't want to set a height for the parent div, as I'd like it to adapt to the content of the child div, and therefore I can't set a % as height for the child div holding the picture. If I set a value in px for the div holding the picture, it won't stretch to the whole length on larger screen.
<div className='bg-cyan md:flex md:pb-4'>
<div className={`relative md:w-${imgWidth}`}>
<Image src={image} alt='' layout='fill' className='object-cover'/>
</div>
<div className='md:w-1/2 flex flex-col justify-evenly font-black'>
<h1 className='font-sans-bold text-6xl mb-6'><span className='text-white'>...</h1>
<p>...</p>
</div>
</div>

Try objectFit="cover" as a prop to Image component
<div className='bg-cyan md:flex md:pb-4'>
<div className={`relative md:w-${imgWidth}`}>
<Image src={image} alt='' layout='fill' objectFit='cover'/>
</div>
<div className='md:w-1/2 flex flex-col justify-evenly font-black'>
<h1 className='font-sans-bold text-6xl mb-6'><span className='text-white'>...</h1>
<p>...</p>
</div>
</div>
Ref: https://nextjs.org/docs/api-reference/next/image#layout

Related

How can I add absolute overlays over an img tag with object-contain behaviour?

I am working on a touch screen display for a museum. The screen will display old photos with touchable zones laid on top of it that reveal more information about people/objects show in the photos.
The screen size is fixed (it's a TV) but the photos could be in any aspect ratio; landscape or portrait.
There will be a header and footer at the top and bottom of the screen. In the middle I want to display the photo as large as possible. That is to say:
if the photo is portrait it should span the full height between the header and footer with empty space to the left and right.
if the photo is landscape (more landscape than the TV is) it should span the full width of the screen from left to right with empty space above and below.
This, I believe, is classic object-fit: contain; behaviour.
What I'm struggling with is adding the overlay on top. This consists of many rectangles that a user can touch. I know the top and left position and width and height of each box as a percent of the image it is overlaying.
I have made a tailwind playground here: https://play.tailwindcss.com/1c8QufeAFj
My understand is that I can't add the overlain boxes as children of the <img> tag, so they are placed in a <div> that is the <img> tag's sibling.
<!-- Check out the tailwind playground to see a live preview -->
<div class="flex h-screen flex-col">
<div id="header" class="bg-gray-500 p-6"><p>Header</p></div>
<!-- Main content which grows to fill the space between the header and footer -->
<main class="grow bg-gray-900">
<!-- Wrapper around the img and it's overlay -->
<div id="wrapper" class="relative">
<!-- The image: Should be as large as possible within main content (object contain style behaviour) -->
<img class="h-full w-full" src="https://placekitten.com/600/400" />
<!-- Div container boxes to draw on top of image (and move and scale with the image) -->
<div class="absolute inset-0 z-10">
<!-- Boxes overlaid on each kitten -->
<div style="left:48%; top:28%; width:11%; height:15%;" class="absolute border-2 border-orange-300"></div>
<div style="left:36%; top:29%; width:10%; height:14%;" class="absolute border-2 border-orange-300"></div>
<div style="left:16%; top:33%; width:10%; height:14%;" class="absolute border-2 border-orange-300"></div>
<div style="left:69%; top:43%; width:11%; height:15%;" class="absolute border-2 border-orange-300"></div>
</div>
</div>
</main>
<div id="footer" class="bg-gray-500 p-6"><p>Footer</p></div>
</div>
Since the boxes' positions and sizes are relative to the image, this sibling div must have the same size as the img at all times.
I can't get this to work with object-fit:contain; the sibling div that contains the boxes doesn't have the same size as the img so the boxes don't line up where they are supposed to.
If I try to find a solution without object-fit then I can either get it to work for portrait photos (using h-full) or landscape photos (using w-full) but I haven't managed to find code that works for both portrait and landscape.

Nesting image elements inside of a div is causing them to overflow a flex container instead of scrolling

I nested a bunch of mapped img elements within a div and set the div's overflow-x to scroll.
<div className='w-full px-2 flex gap-2 overflow-x-scroll scrollbar-none'>
{props?.categoryMovies?.map((movie, i)=> (
<img
id={movie?.id}
key={i}
className='w-[60] h-[60] object-contain'
src={props?.preImg + movie?.poster_path}
/>
))}
</div>
As expected, when I run this code, any img element that flows outside the barrier of the parent div's width is only visible when I scroll along the x-axis.
However, when I try to nest those img elements inside of another div, the behavior changes.
<div className='w-full px-2 flex gap-2 overflow-x-scroll scrollbar-none'>
{props?.categoryMovies?.map((movie, i)=> (
<div className='w-60 h-60'>
<img
id={movie?.id}
key={i}
className='w-full h-full object-contain'
src={props?.preImg + movie?.poster_path} />
</div>
))}
</div>
Instead of maintaining the same results, content that flows out of the main parent div element is visible by default. So, you can say it's as if it breaks out of the barrier of the parent div element and is visible when I scroll on any part of the body of the page, not just when I scroll on the parent container div.
How can I get the second code block to behave like my initial example and have the content become visible only when I scroll on the parent div container?
One way to fix this would be to give each <div> in your flexbox the utility class flex-shrink-0, which will preserve the size of each container.
<div className="w-full px-2 flex gap-2 overflow-x-scroll scrollbar-none">
{props?.categoryMovies?.map((movie, i)=> (
<div className="w-60 h-60 flex-shrink-0">
<img id="{movie?.id}" key="{i}" className="w-full h-full object-contain" src={props?.preImg + movie?.poster_path} />
</div>
))}
</div>
You can see it working here: https://play.tailwindcss.com/KoEroV1coQ

Cropped Full screen oval border with text inside with CSS text

I am struggling to imagine the best way to accomplish a layout I am trying to achieve which includes a static sized oval that is cropped for smaller screens and which contains text inside it that will respond based on the breakpoint.
The design is like this:
So far, I'm here:
I'm trying to achieve this by creating the Oval outside my container div then putting on negative margin on the text to give it the appearance it is inside the oval. I feel like this isn't the right approach.
Currently set up (using Tailwind):
<section id="reading">
<div class="mt-12 border border-black rounded-[50%] overflow-hidden w-[686px] h-72"></div>
<div class="flex flex-col mx-auto md:container">
<div class="self-center justify-center px-8 text-center uppercase -my-80 py-28 text-ts3 font-title-preset">Text Headline Goes Here</div>
</div>
</section>
In my head, for the oval, I would just do margin:auto; overflow:hidden, and width:100% on the div, but that isn't working.
Any pointers on how you would approach this from a better practice perspective?
Thanks!
The approach you're taking separates the oval from the content within. A better way would be to keep them together by wrapping them both in a relatively positioned div and making the oval absolutely positioned to the top and center (then using a transform to center again which is a common pattern) and adding overflow-hidden to the relatively positioned element.
Not sure what your text-ts3 class is meant to do since you did not share your config. But this example uses a few breakpoints with text size classes defined for each and some negative top margin on the text to make things look more vertically centered. Here is the example running on Tailwind Play https://play.tailwindcss.com/3zWymGzXPn
<head>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<section id="reading" class="border border-transparent pt-12">
<div class="overflow-hidden relative mx-auto md:container h-72">
<div class="border border-black rounded-[50%] w-[686px] h-full absolute top-0 left-1/2 -translate-x-1/2"></div>
<div class="h-full flex items-center justify-center max-w-[686px] mx-auto">
<div class="text-center uppercase -mt-4 sm:-mt-6 md:-mt-8 text-5xl sm:text-6xl md:text-7xl max-w-xs sm:max-w-sm">Text Headline Goes Here</div>
</div>
</div>
</section>
You can set the width of the oval to 120% (or a fixed with per breakpoint) and the shrink to 0, so it does not shrink.
<section id="reading">
<div class="flex h-screen w-full justify-center overflow-hidden bg-yellow-100">
<div class="mt-12 flex h-56 w-[120%] shrink-0 items-center justify-center rounded-[50%] border border-slate-300">
<div class="font-semibold">text goes here.</div>
</div>
</div>
</section>
See example in tailwind play.

how to make div scroll internally tailwind css

I have a dashboard with two sides, a nav on the left and the main content on the right, simple. They both are housed by a main div which has the height of the current screen.
I need the main content div to scroll internally not scroll with the entire view when content overflows. All this while the nav on the right remains as is without being affected by the content overflow on the main content div
<main className=" flex flex-row h-screen">
<div className=" w-1/5 h-full flex flex-col flex-grow bg-purple-50">
////This is the side nav
</div>
<div className=" w-4/5 bg-gray-50 h-screen overscroll-auto">
/// this is the main content div that i need the content inside to scroll internally
/// what i mean by this is i dont want the whole page to move when there is a lot of content
/// just the content inside this div
</div>
</main>
How can I achieve this
Codepen
You have to give the main content container a max height of screen height. Kindly refer the pen for experimentation or look at code below.
<main className=" flex flex-row h-screen">
<div className=" w-1/5 h-full max-h-screen overflow-y-auto flex flex-col flex-grow bg-purple-50">
////This is the side nav
</div>
<div className=" w-4/5 bg-gray-50 max-h-screen overflow-y-auto">
/// this is the main content div that i need the content inside to scroll internally
/// what i mean by this is i dont want the whole page to move when there is a lot of content
/// just the content inside this div
</div>
</main>

Tailwind grid dynamic sidebar/navbar width with main 100% width

I need a simple main div column 100% full.
Sometimes a sidebar can appear, with dynamic width.
REPL: https://codesandbox.io/s/tailwind-dynamic-sidebar-kw1ku
In this example you can see I'm not able to change sidebar width (which has every time a new width value) and I'm not able to "stretch" main div to 100% width.
How to do?
<div class="min-h-screen grid grid-cols-12">
<div class="bg-green-500">
<div style={`width: ${randomWidth}px !important;`}>
Sidebar. This has dynamic width.
</div>
</div>
<div class="bg-red-500">
Main. This has full width.
</div>
</div>
I would recommend a simple use of relative and absolute. Here's the codesandbox
<div class="min-h-screen w-full relative">
{#if sidebarVisible}
<div class="bg-green-500 h-full absolute left-0">
<div style={`width: ${randomWidth}px !important;`}>
Sidebar. This has dynamic width.
</div>
</div>
{/if}
<div class="bg-red-500 h-screen">
Main. This has full width.
</div>
</div>
For 100% width, you can use w-full and for full screen height h-screen

Resources