How to change image size using nextjs - css

I have an image in a bootstrap card using next/image. I would like the image to be smaller and not fill the entire top portion of the card. Say about 60% of the original size. I tried to wrap the image in a div container and added some css but did not have any affect on changing the size.
import Image from 'next/image'
import logo from '../public/delta-logo.png'
import { Card, Button } from 'react-bootstrap'
import styles from './landing.module.css'
import 'bootstrap/dist/css/bootstrap.min.css'
export default function LandingPage() {
return (
<Card style={{ width: '18rem' }}>
<Image src={logo} alt='Picture of our Logo' />
<Card.Body className='text-center'>
<Card.Title>Card Title</Card.Title>
<Card.Text>
Some quick example text to build on the card title and make up the
bulk of the card's content.
</Card.Text>
<Button variant='primary'>Go somewhere</Button>
</Card.Body>
</Card>
)
}

for more optimizing you can use this option in Next.config.js:
[image-optimization-nextjs][1]
[1]: https://nextjs.org/docs/basic-features/image-optimization#loader
you don't need to import images on your page. next/image by default recognize /public dir. src="/delta-logo.png"
and You can either use width and height properties in Image tag.

You can either use width and height properties in Image like
<Image src={logo} alt='Picture of our Logo' width={500} height={500}/>
OR
Define a class for your image in your CSS file, and add that className to your Image tag like
<Image src={logo} alt='Picture of our Logo' className='yourClass'/>

Related

How to set Background Image in Nextjs?

I'm using Nextjs and Material-Ui in my project, setting background image is not working as it did in other projects with react. It's my first time using Nextjs.
I've tried importing Image from "next/image" and using the
<Image height={} width={} />
but it's not working like background! I'd appreciate if you have any information about setting background in Nextjs with MUI.
Short answer: In fact, the path to the image is a relative path, and
the goal is to get the absolute path of the image.
To import the image as a background Image in NextJS page can be applied by various methods, but in this case, importing as an image file maybe is more suitable.
import myImage from "../public/imageName.png";
After the code is compiled the myImage will have an object that is considered the details of an image such as "src", "height", "width", and "blurDataURL".
Here is an example of what the object looks like.
{
"src": "/_next/static/media/imageName.7f7cc385.png",
"height": 7730,
"width": 7730,
"blurDataURL": "/_next/image?url=%2F_next%2Fstatic%2Fmedia%myImage.7f7cc385.png&w=8&q=70"
}
Finally, this can have a direct access to the image's absolute path via the src property of myImage object. By using the src property of the myImage, the following code demonstrates how to display an image located in the public folder by MUI Box Component.
<Box
height={789}
width={1440}
sx={{
background: `url(${myImage.src}) center / cover`,
}}
/>
jsx:
<div className={classes.pageContainer}>
//your code here
</div>
css class:
pageContainer: {
width: '100%',
height: '100vh',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
backgroundImage: 'url(IMAGEROUTE/IMAGENAME.svg)',
},

nextjs Image property null

I have a component with dynamic content like so :
<Image width="680" height="400" src={post.imgsrc} alt={post.title} />
I keep having the same error even if I have added the width/height :
Image with src "/imgs/paintings/2022/2.jpg" must use "width" and "height" properties or "layout='fill'" property.
I don't know why, and I wonder why I have to specify width and height since my pictures have different sizes...
One thing to mention is that you can import the images if they are local, if you want that you do not need to use width, height, or fill.
They get provided automatically
Example from the docs:
import profilePic from '../public/me.png'
import Image from 'next/image'
import profilePic from '../public/me.png'
function Home() {
return (
<>
<h1>My Homepage</h1>
<Image
src={profilePic}
alt="Picture of the author"
// width={500} automatically provided
// height={500} automatically provided
// blurDataURL="data:..." automatically provided
// placeholder="blur" // Optional blur-up while loading
/>
<p>Welcome to my homepage!</p>
</>
)
}
This also explains why remote images do need these properties.

How do you change Material UI Grid properties based on screen size?

I'm using Material UI, and I have a grid in the home page. This grid has some properties that I would like to stay regardless on screen size. However, when the screen is lg (1200px) or more, I would like to add negative margin.
Currently, the grid looks like
<Grid container spacing={0} direction="row" maxWidth="lg" margin="auto">
I simply want to add margin-top="-50px if the screen size is 1200px or more. What would be the best way to go about doing that?
The best practice is to separate your styles from your component or element unless you only want to change one thing or two things.
Try to use useStyles. It will make your life much easier.
To better understand what's going on in here, I've recreated your grid below.
import { Grid} from "#material-ui/core";
import React from "react";
const YourComponent = () => {
const classes = useStyles();
return (
<>
<Grid className={classes.myGrid}>
Your Content Goes Here
</Grid>
</>
);
};
export default YourComponent;
Material UI has breakpoints implemented supporting multiple screen sizes. Let's say you create another file for your styles, here is what it would look like:
import { makeStyles } from "#material-ui/core/styles";
export default makeStyles((theme) => ({
toolbar: theme.mixins.toolbar,
myGrid: {
// here goes your margin for large screens and up
[theme.breakpoints.up("lg")]: {
margin: "-50px",
},
//here goes your regular size
}
}));
You should be using negative margins with care though. I'm sure there are better ways to recreate your view.
You should definitely take a look at MUI's documentation on breakpoints.
You can try useMediaQuery from MUI.
const matches = useMediaQuery("(min-width:1200px)");
and
<Grid
container
spacing={0}
direction="row"
maxWidth="lg"
margin={matches ? "-50px auto auto" : "auto"}
>
Another way could be through breakpoints:
<Grid container spacing={0} direction="row" maxWidth="lg" margin="auto" sx={{marginTop: {lg: -50px}}}>

React Native - Visible parent view despite having no margin in between children views

I have a screen set up similarly to the codes below
import React from 'react';
import { StyleSheet, View } from 'react-native';
const App = () => {
const styles = StyleSheet.create({
navContainer:{
height:64,
backgroundColor:'#333333',
},
rowsContainer:{
backgroundColor:'red',
margin:0,
padding:0,
},
});
return (
<View>
<View style={styles.navContainer} />
<View style={styles.rowsContainer}>
<ChildrenRow />
<ChildrenRow />
<ChildrenRow />
<ChildrenRow />
<ChildrenRow />
<ChildrenRow />
<ChildrenRow />
<ChildrenRow />
<ChildrenRow />
<ChildrenRow />
</View>
</View>
);
};
export default App;
ChildrenRow
const ChildrenRow = () => {
return (
<View
onLayout={(event) => {
const {width, height} = event.nativeEvent.layout;
console.log(`Height/Width= ${height} and ${width}`)
}}
style={{
height:59,
width:400,
backgroundColor:'black',
margin:0,
padding:0,
}}/>
)
}
Despite having no margin (nor padding, purposely add in margin:0, padding:0), the view with red background is visible on my OPPO F9, in-between the childrenRows. The same was observed in a few other devices, and also on some firebase test devices.
Using Android Studio's layout inspector showed an even worse result, as per the image below
Also noticed on console, that the heights of some childrenRows are weirdly rounded:
A similar question was asked here, but i couldn't use the solution as i will be adding borderWidth to each children row and the heights are non-static, which might break the UI.
This happens due to Pixel Grid Snapping. You can avoid this by using
import { PixelRatio } from "react-native";
const height = PixelRatio.roundToNearestPixel(8.4)
There might be some solutions to your problem. Try messing around with them. Firstly try rounding up row height to 60 (sometimes devices go crazy with odd numbers in UI). Also try setting style of parent component for rows to flex:1, flexDirection: 'column' if it doesn't work you can go around this problem by making new component as a black colored mask for background with calculated height and width is you have this set. Make sure it's position is fixed, or absolute, and it's zIndex is lower lesser than rows and greater than backgrounds . This last method is kinda brute force but if it works it works.

How can I imitate the look of the outline and label from Material-UI's outlined textfield?

I'm trying to imitate the outlined textfield from Material-UI but I don't know how to hide the border behind the title text.
In the below image, notice how the "Due Date/Time" is taken from the Material-UI library and the title hides the border behind it but when I tried to imitate it with a custom component I just couldn't hide the border.
Alternatively, Is there a better way to use this outline design instead of just implementing it with CSS?
My current component looks liks this:
<div style={inputContainerStyle}>
<div style={{
...titleStyle,
transform: 'translate(-43px, -11px) scale(0.75)',
fontSize: '17px',
color: 'rgba(0, 0, 0, 0.54)',
position: 'absolute',
}}
>
Color
</div>
<div
className="flex-row"
style={{
border: '1px solid rgba(0, 0, 0, 0.23)',
padding: '18.5px 14px',
borderRadius: '4px',
}}
>
{
availableColors.map(color => <div style={colorCircleStyle(color)} />)
}
</div>
</div>
UPDATE
For many scenarios, my later answer (which avoids using TextField and therefore has no side-effects on FormControl context) may be more appropriate: How can I set an static outlined div similar to Material-UI's outlined textfield?
There is a great deal of flexibility in what you can do with TextField. TextField supports plugging in different types of inputs (e.g. Select, input, custom pickers) via the inputComponent property. You could leverage this to put anything inside its labelled outline by creating a custom component like this OutlinedDiv:
import React from "react";
import TextField from "#material-ui/core/TextField";
const InputComponent = ({ inputRef, ...other }) => <div {...other} />;
const OutlinedDiv = ({ children, label }) => {
return (
<TextField
variant="outlined"
label={label}
multiline
InputLabelProps={{ shrink: true }}
InputProps={{
inputComponent: InputComponent
}}
inputProps={{ children: children }}
/>
);
};
export default OutlinedDiv;
The className passed to the inputComponent takes care of the CSS that makes this all work. You can then use this like in the following:
import React from "react";
import ReactDOM from "react-dom";
import OutlinedDiv from "./OutlinedDiv";
import Avatar from "#material-ui/core/Avatar";
import deepOrange from "#material-ui/core/colors/deepOrange";
import deepPurple from "#material-ui/core/colors/deepPurple";
import red from "#material-ui/core/colors/red";
import green from "#material-ui/core/colors/green";
import blue from "#material-ui/core/colors/blue";
import Grid from "#material-ui/core/Grid";
function App() {
return (
<div className="App">
<OutlinedDiv label="Color Picker">
<Grid container justify="center" alignItems="center">
<Avatar style={{ backgroundColor: deepOrange[500] }} />
<Avatar style={{ backgroundColor: deepPurple[500] }} />
<Avatar style={{ backgroundColor: red[500] }} />
<Avatar style={{ backgroundColor: green[500] }} />
<Avatar style={{ backgroundColor: blue[500] }} />
</Grid>
</OutlinedDiv>
<br />
<br />
<OutlinedDiv label="Custom Outlined Thing">
You can put whatever you want in here.
</OutlinedDiv>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
No need to write Outlined div component and all. As we can achieve this using FormControl, FormLabel and Formgroup.
If you follow the Outlined div logic your input fields will lose focus.
The below solution is very easy and quick you just need to wrap your code:
<FormControl component="fieldset" className="fieldset">
<FormLabel component="Legend">Title</FormLabel>
<FormGroup row>
{/*Your Input fields e.g TextField or Select e.t.c*/}
</FormGroup>
</FormControl>
Now using useStyles apply some css:
fieldset: {
width: '100%',
marginBottom: 10,
padding: 10,
border: '1px solid #ddd',
borderRadius: 5
}
The outlined textfield was really tricky to implement. When pushing that feature, we had to consider several options, each with their own drawbacks
SVG Element
Easy to build and animate, but tough to scale with the surrounding elements. If we had gone this route, we would have needed to listen for some type of resize event, which would mean either using a window resize event, which is not robust, or using a newer and less supported feature such as a ResizeObserver/MutationObserver. There are polyfills, but that would have increased the bundle size about 2K for a relatively small feature.
The SVG route is likely what will be used in the future. It is also worth noting that this is how Google's Material Components Web solves the problem.
Plain old border with a background on the label
This is by far the simplest approach, but it is also somewhat inflexible. You can see an example of this in Google's new sign-in flow. There they actually set the background color to white. This is probably a fine approach for plenty of users, but of course won't work if your background is a gradient or some similar edge case. That said, there's no need to worry about resize because it's just a border.
Fieldset and legend
This is what we ended up going with, largely because of its flexibility for end users. Fieldset and its legend component are both built-in ways of attaining pretty much this exact functionality. The big drawbacks to this are that styling across browsers is tough, and the properties we'd be animating on are not performant, such as legend width. Additionally, it's always best to use semantic HTML of course, which this is not, which means we need to use aria-hidden to instruct screen readers to ignore the element.
Depending on your goals, any one of these solutions may work best for you. Beware that getting the perfect solution that solves all of these problems may be very tricky!
Just apply the same background color on the color div as the parent's background color, you can do it by background-color: inherit like this:
<div style={inputContainerStyle}>
<div style={{
...titleStyle,
transform: 'translate(-43px, -11px) scale(0.75)',
fontSize: '17px',
color: 'rgba(0, 0, 0, 0.54)',
position: 'absolute',
background-color:'inherit' **(just add this line)**
}}
>
Color
</div>
<div
className="flex-row"
style={{
border: '1px solid rgba(0, 0, 0, 0.23)',
padding: '18.5px 14px',
borderRadius: '4px',
}}
>
{
availableColors.map(color => <div style={colorCircleStyle(color)} />)
}
</div>
</div>

Resources