Making "View" fill upp entire screen in React Native - javascript

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?

Related

Creating responsive 'Image Map' for elements to match elements of background image (JS/CSS) (React) [duplicate]

I'm trying to create a map of button elements that overlay a full-screen image, positioned over all the 'buttons' depicted on the image. When the image resizes, the button elements should resize as well.
I initially used an SVG image map for this, but it had a positioning bug (the link below) that didn't allow for the video player inside the foreignObject to show.
SVG foreignObject and absolute positioning
I figured using absolute positioning, and JS to measure the width of the background image was the best way to go. However, I'm having trouble making it work.
Below is the project, with the white box needing to be positioned over the background image (the entire box, with chocolates, and the screen).
The image is within a div as a background, like so:
export const BackgroundLightsOn = styled.div`
position: absolute;
background: url(${BgLightsOn});
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
height: 100%;
width: 100%;
border: 1px solid red;
`
Unfortunately, getting the dimensions of this DOM element gets the dimensions of the div, not the image (which is sometimes larger than the viewport). Below is the 'resizing' code, but this connects to backgroundRef (which is the div element the image is the background, not the image itself).
import React, { useEffect, useRef } from 'react';
import {
TruffleTinContainer,
TruffleTinOutside,
} from '../truffle-tin/styledTruffleTin';
export default function TruffleTin({ backgroundRef }) {
const truffleTinRef = useRef();
const initialPos = { x: 150, y: 150 };
const padding = 25;
let truffleBoxWidth = 0;
let truffleBoxHeight = 0;
useEffect(() => {
truffleBoxWidth = truffleTinRef.current.offsetWidth;
truffleBoxHeight = truffleTinRef.current.offsetHeight;
resize();
}, []);
function resize() {
let backgroundDivRect = backgroundRef.current.getBoundingClientRect();
truffleTinRef.current.style.left =
(initialPos.x / truffleBoxWidth) * backgroundDivRect.width -
padding +
'px';
truffleTinRef.current.style.top =
(initialPos.y / truffleBoxHeight) * backgroundDivRect.height -
padding +
'px';
}
useEffect(() => {
window.addEventListener('resize', resize);
return () => window.removeEventListener('resize', resize);
});
return (
<TruffleTinContainer ref={truffleTinRef}>
I'm the truffle tin
</TruffleTinContainer>
);
}
See the GIF below for the issue:
What's the best way to get this div to proportionally match the width of the background image?
(Edit: I changed the 'div with image background' to an img tag, but even then, the getBoundingClientRect shows not the width of the image, but the width of the viewport:
(in other words, even though the image is much wider than the viewport, I'm still getting the viewports dimensions, when what I want is the image's dimensions))
You don't need JS for that. This is achieved with plain CSS, all you need is the button center positions relative to left-top corner of the block. Sample HTML/CSS:
<div class='wrapper'> <!-- Will need this later -->
<div class='container'>
<a class='button' style='--left: 25%; --top: 20%'>1</a>
<a class='button' style='--left: 35%; --top: 80%'>2</a>
</div>
</div>
.container{
position: relative;
background: url('/path/to/image');
background-size: 100% auto;
}
.button{
position: absolute;
left: var(--left);
top: var(--top);
transform: translate(-50%, -50%); /* Move button a bit so its center matches the actual position */
/* These are just for visualization */
width: 50px;
height: 50px;
border-radius: 100%;
background: pink;
display: flex; align-items: center; justify-content: center;
}
The next step is to make .container have a constant width, or at least a constant width/height ratio if you care about vertical resizing. The constant width is achieved with a simple min-width. To avoid horizontal scroll we will add a .wrapper to hide the cut-off sides:
.wrapper{
display: flex;
align-items: center;
max-width: 100%;
overflow: hidden;
}
/* A-and a min-width for .container */
.container{
min-width: 1200px; /* Or whatever */
}
If you need a fixed ratio:
.container::before{
content: '';
display: block;
padding-top: 56.25%; /* 56.25% of the parent width this is, ratio 16x9 */
}
min-width can still be applied if needed. There's an aspect-ratio CSS property that can be used instead of that pseudo-element hack, but it is supported only in relatively fresh browser versions; still might be used if you don't plan supporting a little outdated browsers.

Bounding Rect position not match real element position

I got a strange problem with bounding box. As you can see on screenshot - the position of the bounding box of ad_agency is 1-2 pixels to the right of the position of the real element. I have no odd margins, paddings and etc, all are regular. Little strip(4px in height) below Ad_agency token/chip is positioned from it .getBoundingClientRect() and its width equal to the width of token.
Looks like visual width of chips is less than its bounding box width and it move all past elements out of bounding box (somehow). If i set const width (for example width: 150px;) - problem disappear, but any other options for width gives this bug.
I using typescript, mobx, react, css.
const Container = styled(CFlex)<{color: string}>`
height: 28px;
background-color: ${props => props.color};
border-radius: 2px;
display: inline-flex;
color: white;
margin-right: 12px;
align-items: center;
position: relative;
z-index: 20;
&:hover {
z-index: 23;
}`
don't know if it matters, i use react clone to insert token and add to it mouse events:
{React.cloneElement(this.props.children, {
onMouseLeave: this.referenceMouseHandler,
onMouseEnter: (event) => this.referenceMouseHandler(event, true),
})}
where this.props.children = token
Do anyone know how to solve this problem?
Minimum version where problem occurs(looks like content positioning wrong): enter image description here

Adjust page function, when changing device, just reloading works

I have a function to determine the height of the page, so that the page always stays at the maximum size regardless of the device, without scrolling.
I first take the maximum height of let s = $ (document) .height and then the height of all other elements, such as the header, main footer and footer. I subtract the value of all items by the variable s, which contains the height total. I assign the result to the main height value, so the page is the way I want it.
However, when I change the device to chrome inspection feature, or I leave it in landscape, the page is irregular. So be sure to reload, try using windows.resize by calling a function, but it doesn't adjust, just reloads. I don't know what to do.
I call the function like this:
$("document").ready(function() {
changesize();
$(window).resize(function() {
changesize();
});
};
Any reason you couldn't use css to accomplish this? height: 100vh will keep an element at the viewport height even when resized, and using flex or grid you could stretch and scale the main layout elements however you need them.
body {
margin: 0;
text-align: center;
}
.container {
height: 100vh;
display: flex;
flex-direction: column;
}
header, footer {
background: aliceblue;
flex: 0 0 auto;
}
.content {
flex: 1 1 auto;
background: lightblue;
}
<section class="container">
<header><h1>header</h1></header>
<div class="content">content</div>
<footer>Footer</footer>
</section>

How to set properties of background image in reactJS

I was able to get the background of my header container to show an image. However, i dont k ow how to set the size of the BACKGROUND IMAGE. SO what appears in the heading container just shows a image that is too big to appear in the header container.
I tried to search online
Change the sizes of the containers using vh and vw
Using Inline styles
//App.js
import React from "react";
import NavBar from "./NavBar";
const ContactUs = () => {
return(
<div className="contactUsContainer">
<NavBar/>
<div className="contactUsHeader">
<h2>Contact Us</h2>
</div>
<div>
<span></span>
</div>
</div>
);
}
export default ContactUs;
//app.css
.contactUsContainer {
height: 100%;
width: 100%
}
.contactUsHeader {
display: flex;
flex-direction: column;
align-items: center;
background-image: url("http://www.stapl.co.in/sites/default/files/imagecache/full-zoom/files/projects/6/83/6-83-wartsilla-3.jpg");
background-repeat: no-repeat;
background-size: cover;
height:30vh;
width: 100vw;
background-color: blue
}
Expected Result: background image to show full image, just in smaller size
Actual Result: background image shows very big, which omits much of the image content
The best you can do without any dirty JS is:
background-size: cover;
background-position: center;
Then you just need to pick the right ratio for your image

Stacked divs resizing each other

This is probably going to be a long one:
I'm trying to make a chat application (similar to Slack) with Electron, React and Socket.io. My issue is mostly dealing with React and CSS/Sass though. Right now I've got a few bootstrap, but I'm not really using the grid system at all, so that can/may be scrapped.
The structure of the page is as follows: I've got a footer with a resizable textarea. above it I've got a div that will be holding messages. That div has overflow-y set to scroll, that way the scrollbar is only for the messages and doesn't take the entire page's space. I want the div to get shorter as the footer grows with the textarea. Right now though the div just extends under the footer (and the scrollbar along with it). Since the messages fill the div there's nothing to scroll and no thumb (I think that's the correct term) in the scrollbar.
React component (I've only included one li for the sake of brevity, but in my code I've got bunch):
import React from 'react';
import { Button, Image, Media, Panel } from 'react-bootstrap';
export default class Page extends React.Component {
constructor(props) {
super(props);
this.state = props;
}
footerResize() {
// code to resize messages div, or at least get some information about
// the footer's height
}
render() {
return (
<div className="page">
<div className="sidebar">
</div>
<div className="container-fluid">
<div classname="messages">
<ul>
<li className="message>
<Media>
<Media.Left>
<Image src="#" />
</Media.Left>
<Media.Body>
<Media.Heading>
Name
</Media.Heading>
Message content
</Media.Body>
</Media>
<li>
</ul>
</div>
<footer>
<textarea defaultValue="test text" />
</footer>
</div>
</div>
);
}
}
_page.scss (most of this is from the file name _page.scss but a few properties are pulled in from other files here so I'm only typing one file's contents):
$dark-grey: #383838;
$default-font-color: #FFFFFF;
$light-grey: #474747;
$light-light-grey: #908E8F
$sidebar-width: 250px;
body {
color: $default-font-color;
overflow: hidden;
}
ul {
list-style: none;
}
.page {
background-color: $light-grey;
height: 100vh;
.sidebar {
background-color: $light-light-grey;
position: fixed;
height: 100%;
width: $sidebar-width;
.container-fluid {
margin-left: $sidebar-width;
padding-left: 0px;
padding-right: 0px;
.messages {
overflow-y: scroll;
}
footer {
background-color: $main-green;
bottom: 0;
padding-bottom: 10px;
padding-left: 10px;
padding-right: 10px;
padding-top: 10px;
position: fixed;
width: calc(100% - #{$sidebar-width});
}
}
}
}
I've tried a bunch of different things to get this to work. I've tried a few node modules. I've tried adding event listeners both by adding ref='footer' to the footer and referring to it as this.refs.footer in when adding the event listener and by giving footer and id and using document.getElementById('footer'). The whatever I try I can't get any information about the footer's size in the footerResize. Any help on this would be appreciated. I don't even know if this is something I should be doing with sass properties or whether I need js/React to do this.
You can try out a flexbox based layout.
This for .container-fluid
display: flex;
flex-direction: column;
This for .messages
flex: 1;
Then you remove position: fixed from footer
What this does: it sets the height of .messages to fill its parent's remaining space. So when footer gets bigger, there is less remaining space and .messages will shrink.
Please note that you will need to add vendor prefixes for flexbox depending on your targeted browser support.

Categories

Resources