I have two pieces of text. I need the first piece to be centered horizontally and vertically, and the second to just be right next to it. Currently the code looks like this:
<View style={styles.runningTimeWrapper}>
<Text style={styles.loggedTime}>00:00</Text>
<Text style={[styles.loggedTime, styles.loggedSeconds]}>00</Text>
</View>
How can I style it so the 00:00 is centered? Using fixed widths is not an option as I need this to work on any screen size.
Here is how it looks currently:
Styles:
loggedTime: {
color: Variables.PURPLE,
fontSize: 44,
alignSelf: 'center',
},
loggedSeconds: {
fontSize: 22,
alignSelf: 'flex-end',
paddingBottom: 8
},
runningTimeWrapper: {
flexDirection: 'row',
justifyContent: 'center',
flex: 1,
},
The desired effect is to have the column of hh:mm aligned with the center of the screen, and the seconds directly next to the minutes.
On all 'center' references, I am talking about horizontal center (x-axis), not vertical(y-axis) (which is set using alignItems /self)
You can set the second span to position:absolute, so it will be out of the normal content flow, and ensure the hour/minute to be centered in the container.
.wrapper {
display: flex;
justify-content: center;
position: relative;
font-family: sans-serif;
}
.hm {
font-size: 44px;
}
.s {
font-size: 22px;
position: absolute;
bottom: 5px;
}
<div class="wrapper">
<span class="hm">12:34</span>
<span class="s">56</span>
</div>
In fact, you don't really need flexbox, the text-align:center is probably enough to do it.
.wrapper {
text-align: center;
position: relative;
font-family: sans-serif;
}
.hm {
font-size: 44px;
}
.s {
font-size: 22px;
position: absolute;
bottom: 5px;
}
<div class="wrapper">
<span class="hm">12:34</span>
<span class="s">56</span>
</div>
You'll need 3 inner wrapper views: an empty one on the left and then wrap the small and big numbers in their own wrapper each. Then give the left and right wrappers flex: 1 to make them the same width.
https://rnplay.org/apps/hLBFng
I'm not 100% certain I understand what you're going for. Are you trying to get the loggedTime to be perfectly centered and the loggedSeconds to be offset to the right of that? Or are you simply trying to get both to be center/center?
I think I was able to get something going here by setting flexDirection: 'row' and adding some paddingTop to the seconds.
Here's a demo on rnplay.org
var styles = StyleSheet.create({
loggedTime: {
color: '#FF5500',
fontSize: 44,
alignSelf: 'center',
},
loggedSeconds: {
fontSize: 22,
paddingTop: 20,
paddingBottom: 8
},
runningTimeWrapper: {
flexDirection: 'row',
justifyContent: 'center',
flex: 1,
},
});
Related
I have an editor and several buttons above it on the right. I would like to have a panel just under Button2 that overlays the editor. Then, clicking on Button2 will expand and collapse the panel (which will be easy to implement).
I have written the following code: https://codesandbox.io/s/fervent-mclaren-3mrtyj?file=/src/App.js. At the moment, the panel is NOT under Button2 and does NOT overlay the editor.
Does anyone know how to amend the CSS?
import React from "react";
import { Stack } from "#fluentui/react";
export default class App extends React.Component {
render() {
return (
<div>
<Stack horizontal horizontalAlign="space-between">
<div>Title</div>
<div>Button1 Button2 Button3</div>
</Stack>
<div
style={{
backgroundColor: "yellow",
width: "350px",
height: "50px"
}}
>
A floating panel which is supposed to be always under "Button2" and
overlays the editor.
</div>
<div
style={{
backgroundColor: "gray",
width: "100%",
height: "300px"
}}
>
An editor
</div>
</div>
);
}
}
You need to use position:absolute on floating pane and add it in the editor div which will have position:relative.You can see the result it works fine
On clicking button 2 the floating panel hides/shows alternatively
This will work.
var btn=document.querySelector('.drop_btn');
btn.onclick=function()
{
document.querySelector('.dropdown').classList.toggle('block');
}
*
{
font-family: 'arial';
margin: 0px;
padding: 0px;
}
.menu_pane
{
display: flex;
background: #151515;
color: white;
padding:5px 10px;
align-items: center;
border-bottom: 1px solid rgba(255,255,255,0.2);
}
.menu_pane h3
{
font-weight: normal;
font-size: 18px;
flex-grow: 1;
}
.menu_pane .btn button
{
position: relative;
background: #0971F1;
color: white;
border-radius: 5px;
border:none;
cursor: pointer;
padding: 8px 20px;
margin-right: 10px;
}
.dropdown
{
display: none;
height: 100%;
width: 100%;
top: 0;
left: 0;
color: white !important;
position: absolute;
background: #242424;
border-radius: 0 0 10px 10px;
}
.menu_pane .btn .dropdown p
{
font-size: 14px;
}
.editor_pane
{
position: relative;
background:#151515;
color: white;
min-height: 50vh;
border-radius: 0 0 10px 10px;
padding: 10px;
color: #512DA8;
}
.block
{
display: block;
}
<div class="container">
<div class="menu_pane">
<h3>Title</h3>
<div class="btn">
<button>Button-1</button>
</div>
<div class="btn">
<button class="drop_btn">Button-2</button>
</div>
<div class="btn">
<button>Button-3</button>
</div>
</div>
<div class="editor_pane">
<p>An editor</p>
<div class="dropdown">
<p>A floating panel which is supposed to be always under "Button2" and overlays the editor.</p>
</div>
</div>
</div>
How does this look?
https://codesandbox.io/s/hidden-platform-q3v4kc?file=/src/App.js
I moved the floating pane into the button, made the button position relative, and made the floating pane position absolute.
Note: notice there's no top property on the floating pane. One neat thing about position absolute is if you don't set top, left, bottom, right those positions will be where that box would be if it wasn't position absolute.
Update
I noticed that the overlay needed to cover the "editor" area only and have the example updated with hopefully the right placement of it.
Updated live example: codesandbox
import React from "react";
import { Stack } from "#fluentui/react";
export default class App extends React.Component {
state = { showOverlay: true };
handleToggle = () =>
this.setState((prev) => ({ showOverlay: !prev.showOverlay }));
render() {
return (
<div>
<Stack
horizontal
horizontalAlign="space-between"
style={{ padding: "12px" }}
>
<div>Title</div>
<Stack horizontal>
<button>Button1</button>
<button onClick={this.handleToggle}>
{`Button2 (${this.state.showOverlay ? "Hide" : "Show"} Overlay)`}
</button>
<button>Button3</button>
</Stack>
</Stack>
<div
style={{
backgroundColor: "gray",
width: "100%",
height: "300px",
position: "relative"
}}
>
An editor
<div
style={{
position: "absolute",
inset: "0",
backgroundColor: "rgba(0, 0, 0, 0.70)",
display: this.state.showOverlay ? "flex" : "none",
justifyContent: "center",
alignItems: "center",
color: "#fff"
}}
>
A floating panel which is supposed to be always under "Button2" and
overlays the editor.
</div>
</div>
</div>
);
}
}
Keeping the original example (it had overlay on the whole component except for "Button 2") just in case if it might be useful.
Original
Not sure if I fully understand the desired result, but here is the component implemented with a toggle overlay controlled by Button2.
The overlay is currently set on top of and blocking all child elements except for Button2, so that it works as a "start editing" button, but it can be further adjusted to specify which element it covers to better suit the use case.
Quick demo of the example: codesandbox
import React from "react";
import { Stack } from "#fluentui/react";
export default class App extends React.Component {
state = { showOverlay: true };
handleToggle = () =>
this.setState((prev) => ({ showOverlay: !prev.showOverlay }));
render() {
return (
<div style={{ position: "relative", zIndex: "1" }}>
<Stack
horizontal
horizontalAlign="space-between"
style={{ padding: "12px" }}
>
<div>Title</div>
<Stack horizontal>
<button>Button1</button>
<button style={{ zIndex: "75" }} onClick={this.handleToggle}>
{`Button2 (${this.state.showOverlay ? "Hide" : "Show"} Overlay)`}
</button>
<button>Button3</button>
</Stack>
</Stack>
<div
style={{
position: "absolute",
inset: "0",
backgroundColor: "rgba(0, 0, 0, 0.70)",
zIndex: "50",
display: this.state.showOverlay ? "flex" : "none",
justifyContent: "center",
alignItems: "center",
color: "#fff",
}}
>
A floating panel which is supposed to be always under "Button2" and
overlays the editor.
</div>
<div
style={{
backgroundColor: "gray",
width: "100%",
height: "300px",
}}
>
An editor
</div>
</div>
);
}
}
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
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>
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
I have a view with an icon (from react-native-vector-icons) inside as following:
return (
<View style={styles.iconContainerStyle}>
<Icon name='menu' size={23} style={styles.iconStyle} />
</View>
);
The following is the styling for both the components:
const styles = {
iconContainerStyle: {
justifyContent: 'center',
alignItems: 'center',
height: 30,
width: 35,
borderRadius: 5,
backgroundColor: '#ffffff',
padding: 2
},
iconStyle: {
color: '#2279b4',
}
};
The weird part is that the border radius prop of 5 should give evenly rounded borders, but this is what I get:
Notice that on the right hand side, the borders are sharper then the left part!
I even tried with different borderRaduis values, its still the same concept.
The header you see is provided by react-native-router-flex for my scenes, I think this is also a factor as their styles are also applied on the hamburger button.
A work around (temporarily) is by supplying another parent view with he following style:
<View style={{ justifyContent: 'center', alignItems: 'center', height: 35, width: 40, }}>
The height and width need to be a value bigger then that of the iconContainer.
Please add border: 1px solid #f00; to your code to see if toggle icon is not hidden behind something.
If it looks fine, try to add seperate radius to each angle, Like:
border-top-left-radius: 5px;
border-top-right-radius: 5px;
and so on. Also, try to use border-radius styles with !important.