Force to scroll overflowing item in flexbox - javascript

Im making a container with 3 cards. Each card (brown-ish color in example) has a header with title (sand-buiscuit color) and content (blue one).
What I want to acheive is when the cards are closed (click on header in example), the content (blue) is transitioning to height 0, and so the only visible part is header.
Also when the card is open I want to show the available content but only then, when there is enough available space in container (green).
When 3 cards are open, they have the same height (expand evenly in container), and remaining content (blue) is scrolled.
Is it possible to make?
I prepared a demo codesandbox

I made a small code example using styled-components (just because i like it), you can easily change it to regular react components with css, but this demonstrates the idea.
I created 3 boxes, each box has a default height(40px) and after clicking (which opens it) its height is set to: 100%.
Wrapping all of this boxes with flex container does the trick.
import styled from 'styled-components';
import React, { useState } from 'react';
const MyComponent = () => {
return (
<Container>
<BoxContainer height={100} number={1} />
<BoxContainer height={100} number={2} />
<BoxContainer number={3} />
</Container>
);
};
export default MyComponent;
const Container = styled.div`
display: flex;
flex-direction: column;
justify-content: flex-start;
width: 200px;
height: 400px;
overflow: hidden;
border: 1px solid black;
background-color: blue;
`;
const BoxContainer = ({ number, height = '100' }) => {
const [open, setOpen] = useState(false);
return (
<Box style={{ height: open ? '100%' : '40px' }} onClick={() => setOpen(!open)}>
Box: {number}
{open && <p>Content</p>}
</Box>
);
};
const Box = styled.div`
width: 100%;
overflow: scroll;
background-color: #00b8a2;
border: 1px solid red;
`;
sandbox example here: https://codesandbox.io/s/boxes-fill-container-evenly-when-opened-btlvb

Related

Relative sizing with CSS flex-shrink

I'm using flexbox to display several 3-4 widgets in a single vertical column. Each widget contains a table with a dynamic number of fixed-height rows. I'm trying to accomplish the following:
Widgets should auto-size to their content (remaining as small as possible) (flex-basis:auto)
Widgets should not grow (never appear larger than their content) (flex-grow:0)
Widgets should shrink (showing scrollbars) when the parent container is full (flex-shrink:>0)
Widgets should shrink relative to the size of their content (larger widgets should shrink more than smaller widgets) (flex-shrink:items.length)
Unfortunately, I'm having trouble with the last objective. I've tried using the item count as a value for flex-shrink, assuming it would shrink each widget relatively based on the number of items it contained. However, this doesn't work and leads to some strange/unexpected behavior.
Below is a code snippet demonstrating the issue (JSFiddle here: https://jsfiddle.net/87uwfkv3/5/). In this case (4 widgets of varying sizes) I'd like the second widget to show a single row (since it's only a single item), and the other 3 widgets to be (approximately) the same pixel height as one another with scrollbars.
const App = () => (
<div className="root">
<Widget count={60} />
<Widget count={1} />
<Widget count={600} />
<Widget count={40} />
</div>
);
const Widget = ({ count }) => (
<div className="widget" style={{flexShrink: count}}>
{new Array(count).fill(0).map((o,i) => (
<div key={i}>
item {i+1}
</div>
))}
</div>
);
ReactDOM
.createRoot(document.body)
.render(<App />);
html, body {
background: #aaa;
padding: 5px;
}
.root {
background-color: #ccc;
display: flex;
flex-direction: column;
height: 200px;
gap: 5px;
}
.widget {
background-color: #fff;
border: 1px solid black;
flex: 0 1 auto;
overflow-y: auto;
width: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

How can I vertically align data by 3 when using the react map function?

I have an array object called farm and this data has a total of 10 objects, so when the map function is executed, "hambuger" comes out 10 times.
At this point, I want to vertically align the hamburger data by 3 so that there are 4 lines in total. Of course, there is only one data in the last line.
like this
hamburger hamburger hamburger
hamburger hamburger hamburger
hamburger hamburger hamburger
hamburger
But when I run my code, it all aligns vertically.
like this image
this is my code
const Container = styled.div`
background: lightblue;
width: 100%;
display: inline-block;
flex-direction: row;
`;
const FarmBox = styled.div`
background-color: lavender;
display: inline-block;
flex-wrap: wrap;
width: 10%;
height: 13%;
flex-direction: row;
`;
return (
<>
{farm.map((v, i) => {
return (
<Container key={i}>
<FarmBox>hambuger</FarmBox>
</Container>
);
})}
</>
);
};
export default About;
How can i change my code?
becouse Container is Div and it has 100% width, change this

Making "View" fill upp entire screen in React Native

I am working on a React-native project and stumbled upon issues when setting width and height using percentage values to a View. I have tried to set width: 100% and height: 100% but this does not work.
function CalendarPage() {
return (
<MainWrapper>
<SafeAreaView style={styles.container}>
<ScrollView>
<StyleContentWrapper>
<Paragraph> Hello World! </Paragraph>
</StyleContentWrapper>
</ScrollView>
</SafeAreaView>
</MainWrapper>
);
}
const MainWrapper = styled.View`
flex: 1;
justify-content: center;
align-items: center;
background-color: lightgray;
color: white;
`
const StyleContentWrapper = styled.View`
height: 100%; // this does not work
width: 100%; // this does not work
background-color: red;
padding-top: 40px;
padding-horizontal: 20px;
`
A quick explaination for the components:
MainWrapper covers the entire screen and is the base layer. The reason why it nests SafeAreaView is because this allows me to set a background color on the "safe area".
I have also nested another view called StyleContentWrapperinside a ScrollView, because I want everything inside to be scrollable.
This is the results
StyledContentWrapper or The red box does not cover the entire screen, despite having the styles of width: 100% and height: 100%. Why is this? Setting fixed width and height does work, but this is not the approach I want, because different devices has different widths and heights, and I want it to work for multiple screens with different widths and heights, hence the use of perecentage.
How can I solve this?

How do I center an element horizontally and position other elements relative to it?

I have a search bar in a React application (using material-ui v4). I have a TextField which I always want to be centered horizontally no matter what I put to the left or right of it.
Essentially I want to position everything else relative to the TextField and have it "anchored" in the middle.
I thought this would be simple in CSS but I can't crack it!
I can get the TextField centering on its own no problem with Grid Layout but can't get the button to position relative to it.
This is what I have so far. I feel like I'm missing something really obvious!
import React from "react";
import "./styles.css";
import Paper from "#material-ui/core/Paper";
import TextField from "#material-ui/core/TextField";
import Button from "#material-ui/core/Button";
import { makeStyles } from "#material-ui/styles";
const useStyles = makeStyles({
actionBarRootStyle: {
display: "grid",
justifyItems: "center",
padding: 20
},
textFieldRootStyle: {
border: "1px solid red"
},
buttonRootStyle: {
//?????
}
});
export default function App() {
const styles = useStyles();
return (
<Paper
square={true}
classes={{
root: styles.actionBarRootStyle
}}
>
{/* How do I position this button relative to the TextField so the TextField always stays centered ?*/}
<Button
variant="contained"
color="primary"
classes={{
root: styles.buttonRootStyle
}}
>
Button to the Left
</Button>
<TextField
variant="outlined"
classes={{
root: styles.textFieldRootStyle
}}
/>
</Paper>
);
}
If I'm following correctly, the textfield and button should be within the same container and if you make the container position: relative you can then make the button position: absolute and move its width to the left. Then you can just center the container to achieve the desired effect.
:root {
--TEXTFIELD_WIDTH: 300px;
}
.container {
display: flex;
justify-content: center;
}
.controls {
position: relative;
}
.buttons-left {
position: absolute;
transform: translateX(-100%);
}
.buttons-right {
position: absolute;
transform: translateX(var(--TEXTFIELD_WIDTH));
}
input[type="text"] {
width: var(--TEXTFIELD_WIDTH);
}
<div class="container">
<div class="controls">
<div class="buttons-left">
<button>First</button>
<button>Second</button>
</div>
<div class="buttons-right">
<button>Third</button>
<button>Fourth</button>
</div>
<input type="text" />
</div>
</div>

Modal positioning in css grid system

I am trying to centrally position a modal whose button is clicked in grid column 2. Can anyone please point me in the right direction. I wouldn't want to hard code any margins ofcourse (responsive).
Right now it (green div) is only showing up / restricted to grid-column 2 as seen below .
display: grid;
grid-template-columns: 1fr 1fr;
height: 100%;
margin: 10px;
class Login extends Component {
state = {
isShowModal: false
};
openModal = () => {
this.setState({ isShowModal: true })
}
render() {
const { isShowModal } = this.state;
return (
<>
<div className="grid-1">
</div>
<div className="grid-2">
{isShowModal && <Modal />}
<div className="add">
<button onClick={() => this.openModal()} type="button">Open modal</button>
</div>
</div>
</>
)
}
}
Hi I think what you are looking for is Width max-content with some padding and margin 0px auto.
margin: 0px auto;
width: max-content;
padding: 10px;
max-width:100%; //for responsive purposes.
Then make a surrounding div and position it fixed. And apply the above styles to the divs inside your surrounding div
What this is doing is making a surrounding div that you can design your stuff inside of that will be centered.
Side Note: If you div is falling underneath other elements just set the z-index to 1.
z-index:1;

Categories

Resources