How do I create this layout in Flexbox? - css

I'm trying to create this layout in Flexbox (and React Native) but I can't get it to work. Specifically, the Left and Right buttons refuse to expand to 50% of the width of the container no matter what I do. They are always the size of their content.
I'm using nested containers. The buttons are in a columnar Flex container which is nested in a row Flex container that also contains the image.
Here is my JSX:
<View style={{
display: 'flex',
flex: 1,
flexDirection: 'column'}}>
<Image
style={{flex: 1, zIndex: 1, width: '100%', height: '100%'}}
resizeMode='cover'
resizeMethod='resize'
source={require('./thumbs/barry.jpg')}
/>
<View style={{
display: 'flex',
flexDirection: 'row',
flex: 0,
width: '100%',
height: 100}} >
<Button style='flex: 1' title="LEFT" onPress={() => {}} />
<Button style='flex: 1' title="RIGHT" onPress={() => {}} />
</View>
</View>
All replies are much appreciated...

Maybe this will help you:
.container{
display: flex;
flex-wrap: wrap;
width: 500px;
}
.image{
height: 500px;
flex-basis: 100%;
background-color: green;
}
.button{
box-sizing: border-box;
flex-basis: 50%;
height: 100px;
background-color: red;
border: solid 1px black;
}
<div class="container">
<div class="image"></div>
<div class="button"></div>
<div class="button"></div>
</div>
If you ever have issues with using flexbox, use this resource, it's really helpful for solving flexbox issues. Hopefully you can solve your problem now.

You dont want to use height properties, but using it is a good way to achieve what you want. Here is an example:
You set the image to 90% of the screen height and the buttons container to 10%.
Each button has 50% width
HTML
<div class="container">
<div class="image"></div>
<div class="buttons-container">
<button>Action 1</button><button>Action 2</button>
</div>
</div>
CSS
* {
box-sizing: border-box;
}
body, html {
height: 100%;
margin: 0;
}
.container {
position: relative;
width: 100%;
height: 100%;
}
.container .image {
width: 100%;
height: 90%;
background-image: url('path/to/image');
position: relative;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
.container .buttons-container {
display: flex;
height: 10%;
}
.container .buttons-container button {
width: 50%;
}
Check the example working - https://codepen.io/kaiten/pen/YaYqZO

In consideration of the fact that your code is required in react-native and not react, try this piece of code
<View style={flex:1}>
<Image source={require(path)} style={flex:1}>
<View style={flex:1}>
<View style={flex:1}>
<Button style={flex:1,height:100} title='Left'/>
</View>
<View style={flex:1}>
<Button style={flex:1,height:100} title='Right'/>
</View>
</View>
</View>
Explanation : In react-native you do not need to mention display:flex in your styles since react-native always uses flexBox. When you do flex:1 your container always takes the 100% of the width and the height of it's parents hence doing flex:1,height:'100%',width:'100%' is invalid.
In your
<View style={{
display: 'flex',
flexDirection: 'row',
flex: 0,
width: '100%',
height: 100}} >
you've done flex:0 so this is the equivalent of width:'0%',height:'0%'
Hope this gives you some clarity on the code required.
PS: There might be a possibility that the code i wrote might not work properly due to the <Image> width and height. For eg : If the height of the image decreases and you've given fixed height to your buttons then there might be some white space below your buttons since the height of the <Image> plus the height of the <Button> will not add up to the height of the screen visible.

It seems like Button component do not take style as prop if we look at the codebase of React Native. So the problem is button is not accepting style. So I wrapped button with a view.
Here is sample of working code:
<View style={{
flex: 1,
}}>
<Image
style={{ flex:1, zIndex: 1, width: '100%', height: '100%'}}
resizeMode='cover'
resizeMethod='resize'
source={require('./thumbs/barry.jpg')}
/>
<View style={{
flexDirection: 'row',
height: 100}} >
<View style={{flex:1}}>
<Button title="LEFT" onPress={() => {}} />
</View>
<View style={{flex:1}}>
<Button title="RIGHT" onPress={() => {}} />
</View>
</View>
</View>

Related

how to show full image when resizing react

I'm React Beginner, i have two questions, first question: here i'm using 'allotment' to split two images (resize), you can change the size of images by pulling from middle of those two images
my problem here is, when i'm pulling to left or right to see whole picture, it does not show whole picture it goes over the bottom of page, any idea why?
Second question: below the images I have div which shows with height: 93%`
my question is why height:93 shows the div and height: 100% won't ? shouldn't height:100% take the rest of space left?
try it here: https://codesandbox.io/s/ecstatic-star-1wxx12?file=/src/App.js
import React from "react";
import { Allotment } from "allotment";
import "./styles.css";
import "allotment/dist/style.css";
export default function App() {
return (
<div className="App">
<div style={{ background: "blue", minHeight: "42px" }}>Monitor</div>
<div style={{ display: "flex", height: "100%", background: "darkblue" }}>
<div
style={{
border: "1px solid orange",
width: "100px",
height: "100%",
background: "gray"
}}
>
side content
</div>
<div style={{ width: "100%", height: "100%" }}>
<div
style={{
width: "100%",
height: "100%",
background: "red",
border: "3px solid yellow"
}}
>
<Allotment>
<Allotment.Pane>
<div style={{ height: "40px", background: "brown" }}></div>
<div
style={{
display: "flex",
height: "93%",
flexDirection: "column"
}}
>
<div style={{ flex: "1" }}>
<img
style={{ width: "100%", height: "auto" }}
src={require("./the-mandalorian.jpg")}
alt="cat"
/>
</div>
<div style={{ height: "20px", background: "brown" }}></div>
</div>
</Allotment.Pane>
<Allotment.Pane>
<div style={{ height: "40px", background: "brown" }}></div>
<div
style={{
display: "flex",
height: "93%",
flexDirection: "column"
}}
>
<div style={{ flex: "1" }}>
<img
style={{ width: "100%", height: "auto" }}
src={require("./nature.jpg")}
alt="cat"
/>
</div>
<div style={{ height: "20px", background: "brown" }}></div>
</div>
</Allotment.Pane>
</Allotment>
</div>{" "}
</div>
</div>
</div>
);
}
English is not my mother language so there could be mistakes.
object-fit can help you with that
(Please remove all the styles you have given your images and apply these)
img {
object-fit: cover;
width: 100%;
height: 100%;
}
Video showing the solution a-work
"my question is why height:93% shows the div and height: 100% won't?
shouldn't height:100% take the rest of space left?"
If only width or height are defined without the other, the image's aspect ratio will be preserved and in your case, will result in an unwanted rendering outcome.
since your design have horizontal 2 panes, this leaves very little space for the image to span across the horizontal area, meaning the aspect-ratio of the viewable area is much higher than wide.
You almost always want to maintain the original aspect-ratio, especially for pictures.
Relevant links:
https://stackoverflow.com/a/52682038/104380
https://css-tricks.com/almanac/properties/o/object-fit/

How to center one item with flexbox in React Native?

I have the following component in React Native:
<View styleName="nav">
<Back />
<Image styleName="logo" style={{ alignItems: "center", alignSelf: "center", justifyContent: "center" }} source={Img} />
</View>
As you can see, I am trying just about everything to center the logo, with no luck. Every example I am seeing for flexbox shows > 2 items.
Nav has the following styles:
.nav {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
height: 70;
padding-top: 20;
}
Logo size is set:
.logo {
width: 100;
height: 40;
}
Right now I am getting something like this:
[<Back Logo]
I want something like this:
[<Back Logo ]
You could set the <Back/> component's flex-basis: 50%;
Maybe silly one, but try to wrap logo into the container and set width of that container and width of <Back /> to 33% like this:
<View styleName="nav">
<Back styleName="back" />
<View styleName="logoContainer">
<Image styleName="logo" style={{ alignItems: "center", alignSelf: "center", justifyContent: "center" }} source={Img} />
</View>
</View>
And in styles:
.logoContainer {
width: 33%;
height: 40;
}
.back {
width: 33%;
}
Try this:-
<View style={{flexDirection: 'row'}}>
<View style={{flex: 2}}> // it may vary according to you want
<Back /> // your Back component
</View>
<View style={{flex: 8, alignItems: 'center'}}> // you can also adjust flex
<Image styleName="logo" source={Img} /> // give height width to image
</view>
</View>
<View style={{flexDirection: 'row', alignItems:'center',justifyContent:'center'}}>
<View style={{position:'absolute',left:10}}> // it may vary according to you want
<Back /> // your Back component
</View>
<View style={{}}>
<Image styleName="logo" source={Img} /> // give height width to image
</view>
</View>

Vertical text next to Horizontal Text react native?

I am basically trying to create something like this:
Two boxes, the red one is vertical text and the blue one is horizontal text. The height of the red box should be the same as the blue box
I know that I can make text sideways like that by doing:
transform: [{ rotate: '-90deg'}]
on it, but I am having issues getting the rest to work correctly and having the boxes be aligned and sized properly. Any help would be greatly appreciated!
You should really try playing with the layout of React Native and post what you have tried but here's a sample code
<View style={{ height: 100, flexDirection: 'row'}}>
<View style={{ flex: 1, backgroundColor: 'red', alignItems: 'center', justifyContent: 'center' }}><Text style={{transform: [{ rotate: '-90deg'}]}}>Value</Text></View>
<View style={{ flex: 8, backgroundColor: 'blue', alignItems: 'center', justifyContent: 'center'}}><Text>Short Text</Text></View>
</View>
Result:
So little style pointers:
flexDirection is by default column, so if you don't say its a row,
your views will stack vertically
flex fills your screen in the flexDirection. I have 2 elements in my row with flex, so view1 will take up 1/9th of the space and view2 will take up 8/9th
Alignitems will align your items in the direction of your flex, so horizontally if it's a row, vertically if it's a column.
justifyContent aligns item in the crossaxis, so if your flex is a row, it will align items vertically
Ohey its the same as css
This fiddle should get you close: https://jsfiddle.net/1f8png0r/4/
I would stay away from styling using JS at all costs - (mainly $.css() and $.transform(), etc) It is much slower than CSS and CSS is much easier to maintain down the road -- especially if you can learn to style your selectors nicely!
To break it down a little - you want to create a .row a .left column and a .right column. Inside the .left column you want some text. You want to transform that text and rotate it -- rotate(90deg). I have never used the flex vs. inline-flex for this before now, but after needing to do horizontal text a handful of times I think it is the most robust IMHO.
The main focus is to create the grid as you need it, and to transform the content in the left column of the grid relative to the column (rather than relative to the row).
Hopefully this helps get you closer, cheers!
HTML
<div class="row">
<div class="left">
<span class="h-text">LEFT</span>
</div>
<div class="right">RIGHT</div>
</div>
CSS
.row {
width: 756px;
height: 100px;
border: 2px solid green;
display: flex;
justify-content: center;
align-items: center;
color: white;
}
.right {
width: 80%;
height: 100%;
background: red;
display: inline-flex;
justify-content: center;
align-items: center;
}
.left {
width: 20%;
height: 100%;
background: blue;
position: relative;
display: inline-flex;
justify-content: center;
align-items: center;
}
.left .h-text {
position: absolute;
transform: rotate(-90deg);
}
you could do this.
https://codepen.io/anon/pen/yGepmm
This is an aproach using flexbox. I use sass for clear syntax (no ; )
.sass
div:first-child
display: flex
justify-content: center
align-items: center
transform: rotate(270deg)
width: 100px
background: blue
color: white
text-align: center
vertical-align: middle
div:nth-child(2)
display: flex
padding-left: 2rem
background: lightgreen
justify-content: start-end
align-items: center
color: grey
height: 91px
width: 100%
.html
<section>
<div>
Value
</div>
<div>
Lorem Ipsum
</div>
</section>
It's a very less code implementation, you will have to calculate for now, manually the:
height of div:first-child (which it's the width because the
rotation).
And the height div:nth-child(2).
Hope this helps
I implemented this way giving fixed height and some tweak with flex:
<View style={{flex: 1, paddingTop: 40}}>
<View style={{ flexDirection: 'row', height: 100 }}>
<View style={{ backgroundColor: 'red', justifyContent: 'center' }}>
<Text
style={{
textAlign: 'center',
transform: [{ rotate: '-90deg' }],
}}>
Value
</Text>
</View>
<View
style={{
flex: 1,
backgroundColor: 'aqua',
alignItems: 'center',
justifyContent: 'center',
}}>
<Text>Some text here....</Text>
</View>
</View>
</View>
Here is the link to snack if you want to play around. Might have extra unnecessary styles. You can play with it in the snack.
I hope, you got the idea?
https://snack.expo.io/#roshangm1/humiliated-cookies

Overlapping an icon on React Native

I'd like to have an element overlapping onto an image in react native. I'm new in react native but could do this in CSS in 3 lines of code:
container in position relative.
element in position absolute + bottom: 20px.
Here is my react native code and a screenshot of what it looks like.
<ScrollView style={styles.container}>
<Image
style={styles.profileImage}
source={{uri: blabla}}
/>
<View style={styles.iconContainer}>
<ActionIcon
name={'mode-edit'}
color={colorBrand}
onPress={() => console.log('test')}
/>
</View>
<List containerStyle={styles.list}>
<ListItem
title={'Account Settings'}
/>
<ListItem
title={'Notifications'}
/>
<ListItem
title={'Terms & Conditions'}
/>
<ListItem
title={'Privacy Policy'}
/>
<ListItem
title={'Log Out'}
/>
</ScrollView>
and StyleSheet:
const styles = StyleSheet.create({
container: {
flex: 1
},
profileImage: {
height: 250
},
list: {
borderTopWidth: 0,
flex: 1,
marginTop: 0
},
iconContainer: {
alignSelf: 'flex-end',
right: 10,
bottom: 40,
marginBottom: -60,
zIndex: 1
}
})
So it looks like:
So it looks like exactly like I want it. But I am not liking that zIndex, nor that negative bottomMargin.
I first tried with a container of the iconContainer in position relative, then the iconContainer in position absolute. But to have it displayed you had to set a height. Then you have a white space full width and of the set height with the icon at the right. Which pushes the list down and adds a big white space.
Is there any other options?
Cheers
Add the css property, position: 'absolute' to the element you want to overlap.
I will suggest you to wrap your image and icon in a div and then play with position css
Stack Snippet
.wrapper {
margin-bottom: 40px;
position: relative;
display: inline-block;
}
.wrapper i {
position: absolute;
right: 20px;
bottom: -25px;
width: 50px;
height: 50px;
background: #5ab985;
font-size: 30px;
color: #fff;
text-align: center;
line-height: 50px;
border-radius: 50%;
}
.wrapper img {
display: block;
}
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<div class="wrapper">
<img src="http://lorempixel.com/200/200/sports">
<i class="material-icons">mode_edit</i>
</div>

Image view out of page towards the right unexpectedly

I am rendering a simple view. It consists of an image on the right and some text on the left. This is how it looks like:
return (
<View style={styles.companyContainerStyle}>
<View>
<Text>{this.props.companyNameAr}</Text>
<Text>{this.props.descriptionAr}</Text>
</View>
<View style={styles.imageContainerStyle}>
<Image
style={styles.imageStyle}
source={{ uri: this.props.logo }}
resizeMode='contain'
resizeMethod='auto'
/>
</View>
</View>
);
The following is the styles I applied to make the text and image aligned next to each other:
const styles = {
companyContainerStyle: {
flex: 1,
flexDirection: 'row',
padding: 10
},
imageContainerStyle: {
borderRadius: 5,
borderWidth: 2,
borderColor: '#2279b4',
padding: 1,
},
imageStyle: {
flex: 1,
height: 100,
width: 100,
}
}
The very weird part is that it looks like this on the emulator:
I think the length of the text is pushing the image to the very right out of the screen. I thought that the number of lines would adjust accordingly to fit everything in the screen. However its not the case. How do I make everything look neat given that the length of the text is unknown (it is being rendered from a database)??
#container {
display: flex;
justify-content: space-around;
width: 70%;
height: 400px;;
border: 2px solid grey;
padding: 5px;
}
#top_content {
display: flex;
justify-content: space-around;
align-items: flex-start;
}
#para {
width: 60%;
text-align: justify;
margin: 0px;
}
img {
height: 20%;
width: 20%;
}
<div id="container">
<div id="top_content">
<p id="para">adfasdfadf sadfdaafafdasdfadfadfadfdfad dasadfadfadfadfadgvfa sasadasdaf asdfdfdadfadf</p>
<img src="http://lorempixel.com/400/200" alt="myimg">
</div>
</div>
Something like this can make sure that your text will not push your img outside
Add flex: 1 to imageContainerStyle and also add flex: 1 to View that is container of the two Text components.
Reason for this is that if the Text component does not have container with flex: 1 on it the text will try to take all possible space. The container will restrict that

Resources