Make Images Fit and Resize properly - css

Been trying to fix this myself for awhile and a bit stuck. I can't make these images display properly - Keeping there position in mobile and desktop view.
Probably easy to solve for most people. I am trying to re-make this website, http://www.milkbardigital.com.au/ , as a lesson in web page design .
here's my code
/**
* Created by Hewlbern on 21-Jan-17.
*/
import React from 'react';
import {Image} from 'react-bootstrap';
export default React.createClass ( {
render() {
var background = {
backgroundSize : 'cover'
};
var heroStyle = {
width:'auto',
overflow : 'hidden',
};
var ontop = {
position: 'relative',
display: 'block',
margin: 'auto',
width: '50%',
bottom: '30%',
left: '0',
right: '0',
};
return (
<div style={heroStyle}>
<Image
style={background} responsive
src="http://www.milkbardigital.com.au/wp-content/uploads/2015/11/Milkbar-Home-Background.jpg">
</Image>
<Image
style={ontop} responsive
src="http://www.milkbardigital.com.au/wp-content/uploads/2015/11/Milkbar-Digital-Media.png">
</Image>
</div>
);
}
});

Related

How to implement responsive width for Drawer MUI v5 component?

I am using Material UI v5, and am trying to make a responsive drawer where for smaller devices it will take up 100% of screen width while for larger devices it should only take 1/3 of screen width. But I have no idea how to access Paper property to modify the actual width and make it responsive.
My code:
import { Drawer, styled } from "#mui/material";
const ResponsiveDrawer = styled(Drawer)(({ theme }) => ({
[theme.breakpoints.up("md")]: {
width: "33%", // THIS ONLY CHANGES DRAWER WIDTH NOT PAPER WIDTH INSIDE THE DRAWER
},
[theme.breakpoints.down("md")]: {
width: "100%",
},
}));
export { ResponsiveDrawer };
How I use it:
import { ResponsiveDrawer } from "./Style";
<ResponsiveDrawer
anchor="right"
open={drawer.state}
onClose={() => drawer.onClick(false)}
>
...
</ResponsiveDrawer>
I figured it out shortly after posting the question. This involves inline styling using useMediaQuery.
const largeScreen = useMediaQuery(theme.breakpoints.up("sm"))
<Drawer
anchor="right"
open={drawer.state}
onClose={() => drawer.onClick(false)}
PaperProps={largeScreen ? {
sx: {
width: 450,
}
} : {
sx: {
width: "100%",
}
}
}
>
<CartContent cart={cart} drawer={drawer}/>
</Drawer>
You can add a div inside the <Drawer> or <SwipeableDrawer> component like so and control the width of the div through CSS (or emotion/styled, if you prefer).
<Drawer ...>
<div className="container">...</div>
</Drawer>
.container {
width: 95vw; // for mobile
... add media queries for rest of the screen sizes here
}
In their docs (expand the code blow) they give an example how to access the paper CSS, where you could add your width settings:
const Drawer = styled(MuiDrawer, { shouldForwardProp: (prop) => prop !== 'open' })(
({ theme, open }) => ({
width: drawerWidth,
flexShrink: 0,
whiteSpace: 'nowrap',
boxSizing: 'border-box',
...(open && {
...openedMixin(theme),
'& .MuiDrawer-paper': openedMixin(theme),
}),
...(!open && {
...closedMixin(theme),
'& .MuiDrawer-paper': closedMixin(theme),
}),
}),
);
They add the same mixin to '& .MuiDrawer-paper' in the main drawer css.
So for your responsive drawer you should add this paper selector to your styled CSS (maybe check with the inspector, if its the right one):
const ResponsiveDrawer = styled(Drawer)(({ theme }) => ({
[theme.breakpoints.up("md")]: {
width: "33%",
'& .MuiDrawer-paper': {
width: "33%",
},
},
[theme.breakpoints.down("md")]: {
width: "100%",
'& .MuiDrawer-paper': {
width: "100%",
},
},
}));
More information about customizing nested elements can be found on https://mui.com/material-ui/customization/how-to-customize/#the-sx-prop.

How to load a <div> on top of React google map component?

I am trying to display a small card basically over the google maps component that this https://www.npmjs.com/package/#react-google-maps/api package provides. I set the zIndex to 2 but the <div> still shows below this map component.
The card element is not supposed to respond to any click it's just displayed on first load with the Map component
return (
<div>
<GoogleMap
mapContainerStyle={mapContainerStyle}
zoom={8}
center={center}
></GoogleMap>
<Tracking style={{zIndex: 2}}/>
</div>
);
Tracking is the div that contains information.
Map container style is:
const mapContainerStyle = {
width: "100vw",
height: "100vh",
};
Actually, there are a lot of ways to do it.
Briefly:
You have to add position: 'relative' to the parent component.
You have to add position: 'absolute' and zIndex: 0 to the child component that you want to display as the background.
You have to add position: 'absolute' and zIndex: 1 (or more) to the child component that you want to display as the foreground.
If you use inline styling, you could do this:
Adding top: some_number, left: some_number, right: some_number, or bottom: some_number is optional (depends on what position you want)
Here is the working code sandbox https://codesandbox.io/s/compassionate-rhodes-qbm43
App.js
import "./styles.css";
import Map from "./Map.js";
import Tracking from "./Tracking";
export default function App() {
return (
<div
style={{
position: "absolute",
zIndex: 0,
width: "100%", // or you can use width: '100vw'
height: "100%" // or you can use height: '100vh'
}}
>
<Map />
<div
style={{
zIndex: 1,
position: "absolute",
top: 10,
left: 10,
backgroundColor: "white", // you can use any color value
width: "10%", // or you can use width: any_number
height: "90%" // or you can use height: any_number
}}
>
<Tracking />
</div>
</div>
);
}
Map.js
import React from "react";
import {
GoogleMap,
useLoadScript,
Marker,
InfoWindow
} from "#react-google-maps/api";
import Tracking from "./Tracking";
const libraries = ["places"];
const mapContainerStyle = {
position: "relative",
width: "100%",
height: "100%"
};
const center = {
lat: -33.86882,
lng: 151.20929
};
function Map() {
const { isLoaded, loadError } = useLoadScript({
googleMapsApiKey: process.env.REACT_APP_GOOGLE_MAPS_API_KEY,
libraries
});
if (loadError) return "Error loading maps";
if (!isLoaded) return "Loading Maps";
return (
<div
style={{
position: "absolute",
zIndex: 0,
width: "100%", // or you can use width: '100vw'
height: "100%" // or you can use height: '100vh'
}}
>
<GoogleMap
mapContainerStyle={mapContainerStyle}
zoom={8}
center={center}
></GoogleMap>
</div>
);
}
export default Map;
Tracking.js
import React from "react";
const Tracking = () => {
return (
<div>
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
</div>
);
};
export default Tracking;

Material-UI style buttons on the right

How do you align buttons on the right using Material-UI's makeStyles function?
I have tried using CSS's margin-right: 0 tag, but there is an error using '-' with makeStyles.
I renamed it as 'marginRight' and it still does not work. Also mr: 0 is not valid either. (Using Material-UI's spacing).
The code is trying to make the UI similar to stackOverflow's title layout.
import React from 'react';
import { makeStyles } from "#material-ui/core/styles";
import { Box, Button } from "#material-ui/core";
const style = makeStyles({
titleItemRight: {
color: 'white',
backgroundColor: 'blue',
top: '50%',
height: 30,
align: 'right',
position: 'relative',
transform: 'translateY(-50%)',
}
});
const App = () => {
const classes = style();
return (
<div>
<Box className={classes.titleBar}>
<Button variant='text' className={classes.titleItemRight}>Sign In</Button>
</Box>
</div>
);
};
Change,
align: 'right'
To,
float: 'right'
So the code would look like,
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import { Box, Button } from "#material-ui/core";
const style = makeStyles({
titleItemRight: {
color: "white",
backgroundColor: "blue",
top: "50%",
height: 30,
float: "right",
position: "relative",
transform: "translateY(-50%)"
}
});
const App = () => {
const classes = style();
return (
<div>
<Box className={classes.titleBar}>
<Button variant="text" className={classes.titleItemRight}>
Sign In
</Button>
</Box>
</div>
);
};
Working Codesandbox
I'd suggest using a flexbox for this or just using the AppBar provided already by material ui
https://material-ui.com/components/app-bar/#app-bar
if you'd still like to use Box, just edit the titleBar styles this way and add a spacer element to seperate elements to far right or far left
const style = makeStyles({
titleBar: {
display: 'flex',
width:'100%',
flexFlow: 'row',
},
spacer: {
flex: '1 1 auto'
}
});
and then your component
<Box className={classes.titleBar}>
<LogoHere/>
<div className={classes.spacer}/>
<Button variant="text">
Sign In
</Button>
</Box>

material UI popover - position on small screen

I have been trying for some time to figure out a way to position material ui popover under my anchor, and leave it like that always even on smaller screens.
Here is a sandbox example: https://codesandbox.io/s/material-demo-yvcqu?file=/demo.js
This is the best I got, but the scroll is not really on the body at this point its on the popover container div, and that does not help me.
Just to explain I know I can use AnchorElement with position but on smaller screens, the popover will just hide the Anchor, I would like the popover to always be under it, and just make the body scroll, so I can see the full popover content when i scroll down.
import React from "react";
import {makeStyles,MuiThemeProvider,createMuiTheme} from "#material-ui/core/styles";
import Popover from "#material-ui/core/Popover";
import Button from "#material-ui/core/Button";
export default function SimplePopover() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const theme2 = createMuiTheme({
overrides: {
MuiButton: {
root: {
top: 400
}
},
MuiPopover: {
root: {
},
paper: {
height: 500
}
}
}
});
return (
<div>
<MuiThemeProvider theme={theme2}>
<Button
variant="contained"
color="primary"
onClick={handleClick}
>
Open Popover with anchor
</Button>
<Popover
id="popover-with-anchor"
open={Boolean(anchorEl)}
anchorEl={anchorEl}
onClose={handleClose}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
>
Popover content.
</Popover>
</MuiThemeProvider>
</div>
);
}
Images for example. When popover is bigger than the screen it fits itself in the screen and go overs the anchor
instead of being under the anchor
It's interesting the Popover component doesn't have a property to handle this situation. I ran into a similar issue on a smaller device when I had a long list of data in the popover. To fix this, I just set top myself on the PaperProps property of the Popover component. See below:
<Popover PaperProps={{ style: { top: myAnchor.current ? myAnchor.current.getBoundingClientRect().bottom : 0 } }}></Popover>
Don't do overflow: scroll on root. Instead, do overflowY: auto on paper.
See codesandbox and play around.
Try this:
overrides: {
MuiPopover: {
root: {
// overflow: "scroll"
},
paper: {
left: 50,
top: "500px !important",
height: 50,
overflowY: "auto"
}
}
}

How to mirror and resize the part of image with fixed width and height

I'm building "Tagging from photo" functionality.
When the user move or pinch the square on the image,
PanResponder changes the state of x-coordinate(left), y-coordinate(top), the length of square(thumbSize)
With the data, I want to show the part of square real-time
So this image below should be placed into the left of A, All All from the image above.
Here is the part of render showing the "cropped" image.
console.log(left) // 80
console.log(top) // 200
console.log(thumbSize) // 150
<Image
source={{uri: image}}
style={{height:70, width: 70, bottom: (-top), right: (-left)
}} <- style is not complete. I'm putting some example code
/>
This is continuous problem from: How to show the only part of the image.
It works but the solution doesn't meet my expectation.
It's not changing width and height ( I want to fix resize the image from 'the width of square' to '70' for each width and height)
It breaks the whole style (A, All, All things disappear)
I've been trying to solve this idea for days but couldn't find the exact way.
Update: I almost solved it but resizing matters
I changed Image to CroppedImage (new component)
<CroppedImage
source={{uri: image}}
cropTop={top}
cropLeft={left}
cropWidth={thumbSize}
cropHeight={thumbSize}
width={width(100)}
height={width(100)}
resizeMode="contain" />
Here is CroppedImage
return (
<View style={[{
overflow: 'hidden',
height: this.props.cropHeight,
width: this.props.cropWidth,
backgroundColor: 'transparent'
}, this.props.style]}>
<Image style={{
position: 'absolute',
top: this.props.cropTop * -1,
left: this.props.cropLeft * -1,
width: this.props.width,
height: this.props.height
}}
source={this.props.source}
resizeMode={this.props.resizeMode}>
{this.props.children}
</Image>
</View>
);
It seems working but it can't resize (from square width x height to 70x70).
I made a fiddle to show what calculations you have to do to correctly position and resize your tag image:
$('#image').click(function(event) {
var size_ratio = .6;
var img_src = $(this).attr('src');
var tag = $('#tag-rectangle');
var top_position = tag.height()/2 - event.offsetX*size_ratio;
var left_position = tag.width()/2 - event.offsetY*size_ratio;
$('#tag-rectangle').css({
'background-image': 'url('+img_src+')',
'background-position': top_position +'px '+ left_position + 'px',
'background-size': $(this).width()*size_ratio + 'px ' + $(this).height()*size_ratio + 'px'
});
});
#tag-rectangle {
width: 50px;
height: 50px;
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img id="image" src="http://fakeimg.pl/250x100/" alt="">
<div id="tag-rectangle"></div>
Well, I finally managed to create a working React Native code (never used it before, sorry if it is noobish code) doing the same as in my other answer.
Here is the code:
import React, { Component } from 'react';
import { TouchableWithoutFeedback, ImageBackground, Image, View, StyleSheet } from 'react-native';
const IMAGEURI = 'http://fakeimg.pl/300x300/';
const SIZERATIO = .6;
const IMAGEWIDTH = 300;
const IMAGEHEIGHT = 300;
const CROPIMAGEWIDTH = 100;
const CROPIMAGEHEIGHT = 100;
export default class App extends Component {
state = {
style: {
marginLeft: 0,
marginTop: 0,
},
uri: ''
};
repositionImage(event) {
this.setState({
style: {
marginLeft: CROPIMAGEWIDTH/2 - event.nativeEvent.locationX*SIZERATIO,
marginTop: CROPIMAGEHEIGHT/2 - event.nativeEvent.locationY*SIZERATIO
},
uri: IMAGEURI
});
}
render() {
return (
<View>
<TouchableWithoutFeedback onPress={(event) => this.repositionImage(event)}>
<View>
<Image
style={styles.image}
source={{ uri: IMAGEURI }}
/>
</View>
</TouchableWithoutFeedback>
<View style={styles.tag}>
<ImageBackground style={[styles.cropped,this.state.style]} source={{uri: this.state.uri }} />
</View>
</View>
);
}
}
const styles = StyleSheet.create({
image: {
width: IMAGEWIDTH,
height: IMAGEHEIGHT,
},
tag: {
borderWidth: 1,
borderColor: '#000',
width: CROPIMAGEWIDTH,
height: CROPIMAGEHEIGHT,
overflow: 'hidden'
},
cropped: {
width: IMAGEWIDTH*SIZERATIO,
height: IMAGEHEIGHT*SIZERATIO
}
});
And here is the Snack
I really hope it helped!! Good luck!!
EDIT: Ok I will explain a bit what I'm doing here.
First, I set a State with the parameters that will change based on some event:
state = {
style: {
marginLeft: 0,
marginTop: 0,
},
uri: ''
};
Then, I make the component to get its properties from that state:
< ImageBackground style={[styles.cropped,this.state.style]} source={{uri: this.state.uri }} />
Finally, I prepare the onPress event to call a function which will update the state:
< TouchableWithoutFeedback onPress={(event) => this.repositionImage(event)}>
Here I'm feeding my function with the event object so I will be available to get the coordinates where the user pressed.
That last function takes the data from the event and updates the state. The view will automatically refresh with the new state data.
repositionImage(event) {
this.setState({
style: {
marginLeft: CROPIMAGEWIDTH/2 - event.nativeEvent.locationX*SIZERATIO,
marginTop: CROPIMAGEHEIGHT/2 - event.nativeEvent.locationY*SIZERATIO
},
uri: IMAGEURI
});
}
To position the image, I simply do a math operation:
CROPIMAGEWIDTH is the width of my tag element so to get the center I divide it by 2. Then, I substract the locationX of the event to move the image to the left so the locationX will be at the center of the tag.
That is only for positioning. To scale it just multiply the size of the image and the locationX by the same value. Note I multiplied the width and height of the image with the SIZERATIO in the cropped style
cropped: {
width: IMAGEWIDTH*SIZERATIO,
height: IMAGEHEIGHT*SIZERATIO
}
An example of this scaling stuff:
If your image has 200 width and you want to scale it to a half, you multiply it by 0.5. So if you click at the, say, pixel 180 starting for the left, the equivalent pixel for your scaled image will have to be multiplied by 0.5 too and it will be 90.
If there is something I didn't explaing clearly enough just ask me again a I will be glad to help you.

Resources