I have a series of cards in a flex row. Some cards have longer titles, and therefore have a larger height. If I apply a height of 100% to all cards (using tailwind's h-full class), the smaller cards remain small. If I take that class away, the smaller cards grow to be 100% of the parent container's height, e.g. the height of the tallest card.
You can see a demo here:
<ul className="flex flex-col gap-4 items-stretch md:flex-row md:flex-wrap">
<li className="border-2 rounded-lg p-2 w-80 h-full">...</li>
</ul>
const { useState } = React;
const DifficultyTypes = {
Beginner: "Beginner",
Intermediate: "Intermediate",
Advanced: "Advanced",
}
const sessions = [{"id":"1","title":"Morning Meditation","instructor":"Sarah Johnson","date":"2023-07-15","time":"08:00 AM","duration":30,"difficultyLevel":"Beginner","description":"Start your day with a calming meditation session focused on mindfulness and presence."},{"id":"2","title":"Breathwork for Stress Relief waeghkfvslfhrfhrfg","instructor":"Michael Chen","date":"2023-07-16","time":"12:30 PM","duration":45,"difficultyLevel":"Intermediate","description":"Learn powerful breathing techniques to reduce stress and increase energy levels."},{"id":"3","title":"Advanced Visualization","instructor":"Emma Rodriguez","date":"2023-07-17","time":"05:00 PM","duration":60,"difficultyLevel":"Advanced","description":"Deepen your practice with advanced visualization techniques for personal growth."},{"id":"4","title":"Mindful Movement","instructor":"Sarah Johnson","date":"2023-07-18","time":"10:00 AM","duration":45,"difficultyLevel":"Beginner","description":"Combine gentle movement with mindfulness for an embodied meditation experience."},{"id":"5","title":"Focus and Confkor;gcentration","instructor":"David Kim","date":"2023-07-19","time":"02:00 PM","duration":30,"difficultyLevel":"Intermediate","description":"Strengthen your attention and focus with specialized concentration techniques."},{"id":"6","title":"Deep Relaxation","instructor":"Lisa Patel","date":"2023-07-20","time":"07:30 PM","duration":60,"difficultyLevel":"Beginner","description":"End your day with a deeply relaxing guided meditation for better sleep."},{"id":"7","title":"Mindfulness for Anxiety","instructor":"Michael Chen","date":"2023-07-21","time":"11:00 AM","duration":45,"difficultyLevel":"Intermediate","description":"Learn specific mindfulness practices designed to reduce anxiety and worry."},{"id":"8","title":"Transcendental Meditah;fher;ghj;rgtion","instructor":"Emma Rodriguez","date":"2023-07-22","time":"06:00 AM","duration":60,"difficultyLevel":"Advanced","description":"Experience the profound benefits of transcendental meditation techniques."}];
const Card = ({ session }) => {
return (
<li className="border-2 rounded-lg p-2 w-80 h-full">
<h2 className="text-lg font-bold">{session.title}</h2>
<p className="text-gray-500">{session.instructor}</p>
<p>{session.difficultyLevel}</p>
<div className="flex flex-row gap-2">
<p>{session.date}</p>
<p>{session.time}</p>
</div>
</li>
);
};
function App() {
const [sessionData, setSessionData] = useState(sessions);
const [inputValue, setInputValue] = useState("");
const handleSearch = (e) => {
e.preventDefault();
const filteredSessions = sessions.filter((session) =>
session.title.toLowerCase().includes(inputValue.toLowerCase())
);
setSessionData(filteredSessions);
};
const handleChangeInput = (e) => {
const searchValue = e.target.value;
setInputValue(searchValue);
};
const handleSelectFilter = (e) => {
const filterValue = e.target.value;
console.log(filterValue, typeof filterValue);
const filteredSessions = sessions.filter(
(session) =>
session.difficultyLevel.toLowerCase() === filterValue.toLowerCase()
);
setSessionData(filteredSessions);
};
return (
<main className="min-h-screen p-8 flex flex-col gap-6">
<h1 className="text-3xl font-bold">Mindfulness Sessions</h1>
<div className="border-2 border-blue-500">
<form className="flex flex-row gap-4">
<input type="text" onChange={handleChangeInput} className="w-full" />
<button type="submit" onClick={handleSearch}>
Search
</button>
</form>
</div>
<div>
<select onChange={handleSelectFilter} defaultValue="">
<option value="" disabled>
Select your option
</option>
<option value={DifficultyTypes.Beginner}>
{DifficultyTypes.Beginner}
</option>
<option value={DifficultyTypes.Intermediate}>
{DifficultyTypes.Intermediate}
</option>
<option value={DifficultyTypes.Advanced}>
{DifficultyTypes.Advanced}
</option>
</select>
</div>
<div>
<ul className="flex flex-col gap-4 items-stretch md:flex-row md:flex-wrap">
{sessionData.map((session) => {
return <Card key={session.id} session={session} />;
})}
</ul>
</div>
</main>
);
}
ReactDOM
.createRoot(root)
.render(<App />);
.as-console-wrapper {
display: none !important;
}
<script src=".3.1/umd/react.production.min.js"></script>
<script src=".3.1/umd/react-dom.production.min.js"></script>
<script src="/@tailwindcss/browser@4"></script>
<style type="text/tailwindcss">
@theme {
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
:root {
--background: #ffffff;
--foreground: #171717;
}
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
}
body {
color: var(--foreground);
background: var(--background);
font-family: var(--font-sans), Arial, Helvetica, sans-serif;
}
</style>
<div id="root"></div>
I have a series of cards in a flex row. Some cards have longer titles, and therefore have a larger height. If I apply a height of 100% to all cards (using tailwind's h-full class), the smaller cards remain small. If I take that class away, the smaller cards grow to be 100% of the parent container's height, e.g. the height of the tallest card.
You can see a demo here: https://codesandbox.io/p/sandbox/wonderful-ptolemy-lyh7xh
<ul className="flex flex-col gap-4 items-stretch md:flex-row md:flex-wrap">
<li className="border-2 rounded-lg p-2 w-80 h-full">...</li>
</ul>
const { useState } = React;
const DifficultyTypes = {
Beginner: "Beginner",
Intermediate: "Intermediate",
Advanced: "Advanced",
}
const sessions = [{"id":"1","title":"Morning Meditation","instructor":"Sarah Johnson","date":"2023-07-15","time":"08:00 AM","duration":30,"difficultyLevel":"Beginner","description":"Start your day with a calming meditation session focused on mindfulness and presence."},{"id":"2","title":"Breathwork for Stress Relief waeghkfvslfhrfhrfg","instructor":"Michael Chen","date":"2023-07-16","time":"12:30 PM","duration":45,"difficultyLevel":"Intermediate","description":"Learn powerful breathing techniques to reduce stress and increase energy levels."},{"id":"3","title":"Advanced Visualization","instructor":"Emma Rodriguez","date":"2023-07-17","time":"05:00 PM","duration":60,"difficultyLevel":"Advanced","description":"Deepen your practice with advanced visualization techniques for personal growth."},{"id":"4","title":"Mindful Movement","instructor":"Sarah Johnson","date":"2023-07-18","time":"10:00 AM","duration":45,"difficultyLevel":"Beginner","description":"Combine gentle movement with mindfulness for an embodied meditation experience."},{"id":"5","title":"Focus and Confkor;gcentration","instructor":"David Kim","date":"2023-07-19","time":"02:00 PM","duration":30,"difficultyLevel":"Intermediate","description":"Strengthen your attention and focus with specialized concentration techniques."},{"id":"6","title":"Deep Relaxation","instructor":"Lisa Patel","date":"2023-07-20","time":"07:30 PM","duration":60,"difficultyLevel":"Beginner","description":"End your day with a deeply relaxing guided meditation for better sleep."},{"id":"7","title":"Mindfulness for Anxiety","instructor":"Michael Chen","date":"2023-07-21","time":"11:00 AM","duration":45,"difficultyLevel":"Intermediate","description":"Learn specific mindfulness practices designed to reduce anxiety and worry."},{"id":"8","title":"Transcendental Meditah;fher;ghj;rgtion","instructor":"Emma Rodriguez","date":"2023-07-22","time":"06:00 AM","duration":60,"difficultyLevel":"Advanced","description":"Experience the profound benefits of transcendental meditation techniques."}];
const Card = ({ session }) => {
return (
<li className="border-2 rounded-lg p-2 w-80 h-full">
<h2 className="text-lg font-bold">{session.title}</h2>
<p className="text-gray-500">{session.instructor}</p>
<p>{session.difficultyLevel}</p>
<div className="flex flex-row gap-2">
<p>{session.date}</p>
<p>{session.time}</p>
</div>
</li>
);
};
function App() {
const [sessionData, setSessionData] = useState(sessions);
const [inputValue, setInputValue] = useState("");
const handleSearch = (e) => {
e.preventDefault();
const filteredSessions = sessions.filter((session) =>
session.title.toLowerCase().includes(inputValue.toLowerCase())
);
setSessionData(filteredSessions);
};
const handleChangeInput = (e) => {
const searchValue = e.target.value;
setInputValue(searchValue);
};
const handleSelectFilter = (e) => {
const filterValue = e.target.value;
console.log(filterValue, typeof filterValue);
const filteredSessions = sessions.filter(
(session) =>
session.difficultyLevel.toLowerCase() === filterValue.toLowerCase()
);
setSessionData(filteredSessions);
};
return (
<main className="min-h-screen p-8 flex flex-col gap-6">
<h1 className="text-3xl font-bold">Mindfulness Sessions</h1>
<div className="border-2 border-blue-500">
<form className="flex flex-row gap-4">
<input type="text" onChange={handleChangeInput} className="w-full" />
<button type="submit" onClick={handleSearch}>
Search
</button>
</form>
</div>
<div>
<select onChange={handleSelectFilter} defaultValue="">
<option value="" disabled>
Select your option
</option>
<option value={DifficultyTypes.Beginner}>
{DifficultyTypes.Beginner}
</option>
<option value={DifficultyTypes.Intermediate}>
{DifficultyTypes.Intermediate}
</option>
<option value={DifficultyTypes.Advanced}>
{DifficultyTypes.Advanced}
</option>
</select>
</div>
<div>
<ul className="flex flex-col gap-4 items-stretch md:flex-row md:flex-wrap">
{sessionData.map((session) => {
return <Card key={session.id} session={session} />;
})}
</ul>
</div>
</main>
);
}
ReactDOM
.createRoot(root)
.render(<App />);
.as-console-wrapper {
display: none !important;
}
<script src="https://cdnjs.cloudflare/ajax/libs/react/18.3.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js"></script>
<script src="https://unpkg/@tailwindcss/browser@4"></script>
<style type="text/tailwindcss">
@theme {
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
:root {
--background: #ffffff;
--foreground: #171717;
}
@media (prefers-color-scheme: dark) {
:root {
--background: #0a0a0a;
--foreground: #ededed;
}
}
body {
color: var(--foreground);
background: var(--background);
font-family: var(--font-sans), Arial, Helvetica, sans-serif;
}
</style>
<div id="root"></div>
The styles are applied in the Card.tsx component. I currently have h-full
applied, and the cards are varying heights. Remove that and the cards are all uniform.
What I want to understand is why this happens? Intuitively, I would expect height: 100% to fill the available height. I don't understand why this would instead make it shrink.
Share Improve this question edited Mar 10 at 22:08 Ori Drori 194k32 gold badges238 silver badges229 bronze badges asked Mar 10 at 21:53 crevuluscrevulus 2,5083 gold badges25 silver badges64 bronze badges4 Answers
Reset to default 1Why does adding
height: 100%
cause a child to shrink, but removing it causes child to grow to fill space vertically?
Because height: 100%
is computing to auto
(content height) while overriding align-items: stretch
. But when height: 100%
is removed, align-items: stretch
is free to work.
Here's a more complete explanation of the problem.
Percentage heights require a height specified on the parent.
The CSS
height
property, when used with a percentage value, is calculated with respect to the element's containing block. If the height of the containing block is not specified (and the element is not absolutely positioned), then the value computes toauto
, meaning the height of the content.So your cards (
li
) haveheight: 100%
applied. But there's no height specified on the containing block (the parentul
). Soheight: 100%
isn't doing anything and all cards are just the height of the content. That's what you're seeing.For illustration purposes, add
ul { height: 250px }
to your code. Nowheight: 100%
is working. All cards have equal height.For a more detailed explanation see my answer here:
- Working with the CSS
height
property and percentage values
- Working with the CSS
The
height
property overridesalign-items: stretch
.With
align-items: stretch
in your code, the flex items will expand across all available space in the cross axis. Except theheight
property effectively overrides this setting.For illustration purposes, remove the
height: 100%
from the flex items (li
). Nowalign-items: stretch
works. All cards have full and equal height.You can also try
align-items: flex-start
withoutheight: 100%
. This will emulate the rendering of your original code (as it packs the items to fit their content).
in Card.tsx
you give the li
tag w-80
style if you do not want to card shrink just remove this style
try this code. past it in Card.tsx
import React from "react";
import type { Session } from "../data";
interface ICardProps {
session: Session;
}
const Card = ({ session }: ICardProps) => {
return (
<li className="border-2 rounded-lg p-2 h-full">
<h2 className="text-lg font-bold">{session.title}</h2>
<p className="text-gray-500">{session.instructor}</p>
<p>{session.difficultyLevel}</p>
<div className="flex flex-row gap-2">
<p>{session.date}</p>
<p>{session.time}</p>
</div>
</li>
);
};
export default Card;
Add flex-shrink: 0 to child cards to prevent shrinking. I think you can use this code snippet.
.card { flex-shrink: 0; height: 100%; }
It doesn’t really make sense to set the height of a flex child, especially in the case where the flexbox permits wrapping. So what would height: 100%
mean in this case? The container height or the line height?
My recommendation is to rely on align-items: stretch
(the default) to keep the heights consistent, and don’t define heights on your flex items.
I don’t know the answer to your question. What I can say, though, is that if the flex container has a definite height, setting height: 100%
on a flex item does cause the item to take the same height. However, if the flex container has indefinite height (auto), setting height: 100%
on a flex item appears to override align-items: stretch
, which kinda makes sense, but its actual height becomes more like what you would get with align-items: start
or height: max-content
, which makes less sense.
const s = ['<span>height: 100% plus<br>definite container height</span>']
for (let i = 2; i <=50; i++) {
s.push(`<span>${i}</span>`)
}
document.querySelector('.d5').innerHTML = s.join('')
.d {
display: flex;
gap: 1em;
margin-bottom: 2em;
/*
THIS IS THE DEFAULT VALUE
align-items: stretch;
*/
}
.d > * {
border: 2px solid red;
background: pink;
}
:is(.d2, .d4) {
align-items: start;
}
:is(.d4, .d5) {
height: 5em;
}
.d5 {
flex-wrap: wrap;
background: yellow;
}
:is(.d3, .d4, .d5) > :first-child {
height: 100%;
box-sizing: border-box;
}
<div class="d d1">
<span>align-items: stretch<br>(default)</span>
<span>Two<br>Two<br>Two</span>
</div>
<div class="d d2">
<span>align-items: start</span>
<span>Two<br>Two<br>Two</span>
</div>
<div class="d d3">
<span>height: 100%</span>
<span>Two<br>Two<br>Two</span>
</div>
<div class="d d4">
<span>height: 100% plus<br>definite container height</span>
<span>Two<br>Two<br>Two</span>
</div>
<div class="d d5">
</div>
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744821815a4595662.html
评论列表(0条)