I want to add 'show more' button for overflowed elements then only after clicking on shoe more, I want to show a new line. Here is my code: https://codesandbox.io/s/distracted-microservice-ld267?file=/src/App.js Here is my case we need to do it for an overflowed property like color, Data will be dynamic show for size also if there are more elements, we need to do that. This is the UI for which I want to make, just check It'll help you
-
Please post a [Minimal, Complete, and Reproducible](https://stackoverflow.com/help/minimal-reproducible-example) code example of the relevant code. – Drew Reese Oct 29 '20 at 04:25
-
I think what you are looking for is [here](https://stackoverflow.com/questions/3922739/limit-text-length-to-n-lines-using-css). Please check – Kiran Oct 29 '20 at 05:23
-
A lot of those answers are based on rendering text, which doesn't apply here unfortunately. It'd be amazing if line-clamp applied to arbitrary elements as well – Zachary Haber Oct 29 '20 at 05:54
1 Answers
Here's a solution: the main way this works is by knowing the size that the containing div needs to be, so we can set the height to be the height of one row. Then set overflow: hidden
to hide the display of everything past the first row.
This uses CSS variables to allow for more dynamic setting of the sizes of the color squares (based on the buttons that you had showing in the code). Each of the size buttons change the --size
CSS variable to change the square sizes.
The height of the containing div is thus height: calc(var(--size) + var(--margin) * 2);
which dynamically calculates the height based on the variables so it'll change when the color-blocks change size from the button presses.
The "Show More"/"Show Less" button toggles the showMore
state.
const { useState } = React;
const sizeToNumber = {
standard: "30px",
medium: "50px",
small: "15px",
large: "75px",
"Extra Large": "100px",
"Extra Small": "5px"
};
function App() {
// The current size in pixels - To be used as a CSS variable
const [size, setSize] = useState(sizeToNumber.standard);
const onSizeChange = (val) => {
// Convert from the string text to a pixel value
setSize(sizeToNumber[val]);
};
// State for hiding and showing the extra rows
const [showMore, setShowMore] = useState(true);
let data = [
{
id: 1,
name: "Color",
value: [
"red",
"green",
"yellow",
"blue",
"red",
"green",
"yellow",
"blue",
"red",
"green",
"yellow",
"blue",
"red",
"green",
"yellow",
"blue",
"red",
"green",
"yellow",
"blue",
"red",
"green",
"yellow",
"blue"
]
},
{
id: 2,
name: "Size",
value: [
"standard",
"medium",
"small",
"large",
"Extra Large",
"Extra Small"
]
}
];
return (
// Setup --size and --margin CSS variables
<div style={{ margin: "5px", "--size": size, "--margin": "5px" }}>
{data.map((d) => {
const isColor = d.name.toLowerCase().includes("color");
const hiddenClass = isColor && !showMore ? "hide-rows" : "";
return (
<div key={d.id}>
<div>{d.name}</div>
<div
style={{ background: "aqua" }}
// Set a class if the extra rows should be hidden
className={"flex " + hiddenClass}
>
{d.value.map((val, index) => {
if (isColor) {
return (
<div
key={index}
// This class applies width/height/margin
// based on the variables
className="color-block"
style={{
background: val,
display: "inline-block"
}}
></div>
);
}
return (
<button
key={val}
// Change the --size variable based on the button pressed!
onClick={() => onSizeChange(val)}
className="btn btn-primary m-2"
>
{val}
</button>
);
})}
</div>
</div>
);
})}
<button
className="btn btn-primary m-2"
// Toggle showing/hiding everything
onClick={() => setShowMore(!showMore)}
>
{showMore ? "Show Less" : "Show More"}
</button>
</div>
);
}
ReactDOM.render(<App/>,document.getElementById('root'))
.App {
font-family: sans-serif;
text-align: center;
}
/* Setup a flex grid to the color-block's parent to make
things render consistently */
.flex {
display: flex;
flex-wrap: wrap;
}
/* apply margin/width/height variables to the color blocks */
.color-block {
margin: var(--margin);
width: var(--size);
height: var(--size);
}
/* When the extra rows should be hidden, set the height and no overflow
Height is calculated based on the size + (margin * 2)
This way things can be dynamically changed, but this will remain possible to use
since we need to know the height in order to hide things in a reasonable way*/
.hide-rows {
height: calc(var(--size) + var(--margin) * 2);
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<div id="root" />
Here's the same general principle with the button moved to be inline with the color, and the fun changing of the color swatch sizes removed.
Main difference here is that it uses a flexbox span around the color's div to make it so the "Show More" button appears inline.
const { useState } = React;
function App() {
// State for hiding and showing the extra rows
const [showMore, setShowMore] = useState(false);
let data = [
{
id: 1,
name: "Color",
value: [
"red",
"green",
"yellow",
"blue",
"red",
"green",
"yellow",
"blue",
"red",
"green",
"yellow",
"blue",
"red",
"green",
"yellow",
"blue",
"red",
"green",
"yellow",
"blue",
"red",
"green",
"yellow",
"blue"
]
},
{
id: 2,
name: "Size",
value: [
"standard",
"medium",
"small",
"large",
"Extra Large",
"Extra Small"
]
}
];
return (
<div style={{ margin: "5px" }}>
{data.map((d) => {
const isColor = d.name.toLowerCase().includes("color");
const hiddenClass = isColor && !showMore ? "hide-rows" : "";
return (
<div key={d.id}>
<div>{d.name}</div>
{/* Extra span around the flex container to make the
flex container and the show more button inline */}
<span style={{ display: "flex" }}>
<div
style={{ background: "aqua" }}
// Set a class if the extra rows should be hidden
className={"flex " + hiddenClass}
>
{d.value.map((val, index) => {
if (isColor) {
return (
<div
key={index}
// This class applies width/height/margin
// based on the variables
className="color-block"
style={{
background: val,
display: "inline-block"
}}
></div>
);
}
return (
<button key={val} className="btn btn-primary m-2">
{val}
</button>
);
})}
</div>
{/* Only display the button on the color section */}
{/* It is super annoying to try and calculate to determine
if there's a need for the show more button.
Though doable if you know the size ahead of time*/}
{isColor && (
<button
className="btn btn-primary"
// The button needs to align itself to the top rather than default stretch
style={{ alignSelf: "flex-start", marginLeft: "5px" }}
// Toggle showing/hiding everything
onClick={() => setShowMore(!showMore)}
>
{showMore ? "Show Less" : "Show More"}
</button>
)}
</span>
</div>
);
})}
</div>
);
}
ReactDOM.render(<App />,document.getElementById('root'))
.App {
font-family: sans-serif;
text-align: center;
}
/* Setup a flex grid to the color-block's parent to make
things render consistently */
.flex {
display: flex;
flex-wrap: wrap;
/* Setup --size and --margin CSS variables */
--size: 30px;
--margin: 5px;
}
/* apply margin/width/height variables to the color blocks */
.color-block {
margin: var(--margin);
width: var(--size);
height: var(--size);
}
/* When the extra rows should be hidden, set the height and no overflow
Height is calculated based on the size + (margin * 2)
This way things can be dynamically changed, but this will remain possible to use
since we need to know the height in order to hide things in a reasonable way*/
.hide-rows {
height: calc(var(--size) + var(--margin) * 2);
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<div id="root" />

- 10,376
- 1
- 17
- 31
-
thanks for that. But i think you have misunderstood the question, I've edited my post with an image, you can see and then do that. The thing is like color size is also a property and we also need to do it for size. Just check the image at the end of my post. – Ashutosh Kumar Oct 29 '20 at 05:03