Has anyone build webpages using react.js and the Material UI library? How should I resize the icon size? It is a svg icon.
I just built an "create new" component, which is a piece of material paper with a content add button on the top. Here is the code.
import React from 'react';
import Paper from 'material-ui/lib/paper';
import ContentAdd from 'material-ui/lib/svg-icons/content/add';
import IconButton from 'material-ui/lib/icon-button';
const styleForPaper = {
width: '96vw',
height: '20vh',
margin: 20,
textAlign: 'center',
display: 'inline-block',
};
const styleForButton = {
'marginTop': '7vh',
};
const PaperToAddNewWidgets = () => (
<div>
<Paper style={styleForPaper} zDepth={2}>
<IconButton
style={styleForButton}
touch={true}
tooltip="Add New Widget">
<ContentAdd/>
</IconButton>
</Paper>
</div>
);
export default PaperToAddNewWidgets;
It looks OK (make sure you are viewing it at full size), but the icon is too small. Then I opened the chrome dev tool, and saw the following html code.
<div style="background-color:#ffffff;transition:all 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms;box-sizing:border-box;font-family:Roboto, sans-serif;-webkit-tap-highlight-color:rgba(0,0,0,0);box-shadow:0 3px 10px rgba(0,0,0,0.16),
0 3px 10px rgba(0,0,0,0.23);border-radius:2px;width:96vw;height:20vh;margin:20px;text-align:center;display:inline-block;mui-prepared:;" data-reactid=".0.2.0.1.0"><button style="border:10px;background:none;box-sizing:border-box;display:inline-block;font:inherit;font-family:Roboto, sans-serif;tap-highlight-color:rgba(0, 0, 0, 0);cursor:pointer;text-decoration:none;outline:none;transform:translate3d(0, 0, 0);position:relative;transition:all 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms;padding:12px;width:48px;height:48px;font-size:0;margin-top:7vh;mui-prepared:;-webkit-appearance:button;" tabindex="0" type="button" data-reactid=".0.2.0.1.0.0"><div data-reactid=".0.2.0.1.0.0.0"><span style="height:100%;width:100%;position:absolute;top:0;left:0;overflow:hidden;mui-prepared:;" data-reactid=".0.2.0.1.0.0.0.0"></span><div style="position: absolute; font-family: Roboto, sans-serif; font-size: 14px; line-height: 32px; padding: 0px 16px; z-index: 3000; color: rgb(255, 255, 255); overflow: hidden; top: -10000px; border-radius: 2px; opacity: 0; left: -44px; transition: top 0ms cubic-bezier(0.23, 1, 0.32, 1) 450ms, transform 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms, opacity 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms; box-sizing: border-box; -webkit-user-select: none;" data-reactid=".0.2.0.1.0.0.0.1:0"><div style="position: absolute; left: 50%; top: 0px; transform: translate(-50%, -50%); border-radius: 50%; transition: width 0ms cubic-bezier(0.23, 1, 0.32, 1) 450ms, height 0ms cubic-bezier(0.23, 1, 0.32, 1) 450ms, backgroundColor 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms; width: 0px; height: 0px; background-color: transparent;" data-reactid=".0.2.0.1.0.0.0.1:0.0"></div><span style="position:relative;white-space:nowrap;mui-prepared:;" data-reactid=".0.2.0.1.0.0.0.1:0.1">Add New Widget</span></div><svg style="display:inline-block;height:24px;width:24px;transition:all 450ms cubic-bezier(0.23, 1, 0.32, 1) 0ms;fill:rgba(0, 0, 0, 0.87);mui-prepared:;-webkit-user-select:none;" viewBox="0 0 24 24" data-reactid=".0.2.0.1.0.0.0.1:2:$/=10"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" data-reactid=".0.2.0.1.0.0.0.1:2:$/=10.0"></path></svg></div></button></div>
Using chrome dev tool, I revised the svg icon size and the viewbox property of svg and made the icon larger in browser. But I am not sure how I can resize the icon size in my code. If I write a CSS file to revise the svg it will be problematic if there are more than one svg elements.
do this
<SomeIcon className="svg_icons"/>
.svg_icons {
transform: scale(1.8);
}
just use scale :D it works
Note: iconStyle prop is no longer supported on IconButton Material UI making this answer obsolete
You have to set the size of the icon in the iconStyle prop in <IconButton>. Example below from the material-ui docs.
From my experience, if you set just the height or the width, nothing happens--only seems to work when you set height & width to the same value.
import React from 'react';
import IconButton from 'material-ui/IconButton';
import ActionHome from 'material-ui/svg-icons/action/home';
const styles = {
largeIcon: {
width: 60,
height: 60,
},
};
const IconButtonExampleSize = () => (
<div>
<IconButton
iconStyle={styles.largeIcon}
>
<ActionHome />
</IconButton>
</div>
);
No. Most of the other answers are unsatisfactory and are poor practice, at least in 2021. This answer is literally answered in the documentation here and doesn't require any CSS hacks to get working.
In MUI, the Button and IconButton components are just essentially wrappers that nest the child Icon element in an <a> or <Link> (react-router) element. They don't have any intrinsic control over the size. Thus, to increase the button size, just increase the size of the Icon child of IconButton using the fontSize property. This will automatically make the button larger.
For instance, to make the IconButton below larger:
<IconButton>
<Icon />
</IconButton>
We just increase the size of the Icon child directly.
<IconButton>
<Icon fontSize="large" />
</IconButton>
However, this is largest size you can specify with the fontSize property. To go even larger, we must configure the CSS font-size property manually.
<IconButton>
<Icon style={{ fontSize: 60 }} />
</IconButton>
Simple as.
EDIT: Apparently, for whatever reason, Button components have a size property that allows their size to be controlled, but IconButton components don't. I'm not sure why MUI is so inconsistent...
I faced the same issue while using the last React version (which is today v16.13.1) and Material-ui (which is today v4.9.14).
How I solved it?
By simply adding this style to the icon button
MyIconButton: {
'& svg': {
fontSize: theSizeIWant
}
}
Complete example
import React from "react";
import { makeStyles } from '#material-ui/core/styles';
import IconButton from '#material-ui/core/IconButton';
import DeleteIcon from '#material-ui/icons/Delete';
const useStyles = makeStyles((theme) => ({
deleteIcon1: {
'& svg': {
fontSize: 25
}
},
deleteIcon2: {
'& svg': {
fontSize: 50
}
},
deleteIcon3: {
'& svg': {
fontSize: 75
}
},
deleteIcon4: {
'& svg': {
fontSize: 100
}
}
}));
export default function App() {
const classes = useStyles();
return (
<div className="App">
<h1>fontSize: 25</h1>
<IconButton className={classes.deleteIcon1}>
<DeleteIcon />
</IconButton>
<h1>fontSize: 50</h1>
<IconButton className={classes.deleteIcon2}>
<DeleteIcon />
</IconButton>
<h1>fontSize: 75</h1>
<IconButton className={classes.deleteIcon3}>
<DeleteIcon />
</IconButton>
<h1>fontSize: 100</h1>
<IconButton className={classes.deleteIcon4}>
<DeleteIcon />
</IconButton>
</div>
);
}
and the result will be:
Live running code
I created this codesandbox.
Hope this helps!
With the latest version of material-ui (3.1.0), you can change padding of IconButton and fontSize of SvgIcon to update the looks.
const styles = theme => ({
smallButton: {
padding: 6
},
largeButton: {
padding: 24
},
largeIcon: {
fontSize: "3em"
},
input: {
display: "none"
}
});
function IconButtons(props) {
const { classes } = props;
return (
<div>
<IconButton className={classes.smallButton} aria-label="Delete">
<DeleteIcon fontSize="small" />
</IconButton>
<IconButton aria-label="Delete">
<DeleteIcon fontSize="large" />
</IconButton>
<IconButton className={classes.largeButton} aria-label="Delete">
<DeleteIcon className={classes.largeIcon} />
</IconButton>
</div>
);
}
Live demo
You could just use the fontSize attribute on the child node of IconButton element, that is, in your case - ContentAdd node.
<IconButton
style={styleForButton}
touch={true}
tooltip="Add New Widget">
<ContentAdd fontSize="large" />
</IconButton>
There are 4 options available - inherit, default, small and large.
Source - https://material-ui.com/api/icon/#props
When you need that for your global project you might add a new variant to your MUI theme.
components: {
MuiSvgIcon: {
variants: [
{
props: { fontSize: 'huge' },
style: {
fontSize: '5rem',
},
},
],
},
}
In order to get it worked for TS, you might need to extend the module declarations:
declare module '#mui/material/SvgIcon' {
interface SvgIconPropsSizeOverrides {
huge: true;
}
}
usage:
<HomeIcon fontSize="huge" />
I also wrote a little post on dev.to
this worked for me
fontSize="large"
<Badge badgeContent={4} color="primary" >
<CameraAltIcon fontSize="large" />
</Badge>
look Props --> fontSize
https://material-ui.com/api/icon/
For the current version of MUI (v5.8.5) there is a fontSize prop on the icons with different set sizes of 'small', 'medium', 'large' so you could do something like:
<HomeIcon fontSize="small" />
If one of those set sizes doesn't fit your needs there is also the option to use 'inherit' if you'd like it to match the font size of the container it is in and not have its own separate size.
Lastly, you could use the sx property which MUI places on all its components and in there it will accept the fontSize property which allows you to set the size directly to the icon. For instance:
<WhatshotIcon sx={{ fontSize: 140 }} />
https://mui.com/material-ui/icons/#size
There are two ways of enlarging the svg, one is to override the style with iconStyle, the other is to edit the code found in https://github.com/callemall/material-ui/blob/master/src/SvgIcon/SvgIcon.js
Note: ContentAdd imports from SvgIcon
const mergedStyles = Object.assign({
..
height: 24, // <-- change default height
width: 24, // <-- change default width
..
}, style);
return (
<svg
{...other}
..
style={prepareStyles(mergedStyles)}
..
>
I am using IconStyle prop to change the size of svg icon.
<IconButton
tooltip="Add New Group"
tooltipPosition="top-center"
style={{padding: 0, height: 0}}
iconStyle={{height: 31, width: 48}}
onClick={e => this.openNewList()}
disabled={!this.state.newAvailable}>
<ActionHome />
</IconButton>
There is always simple things to do
give an classname to your material ui icon
And go to your css file and give
height:40px !important and width 40px !impoetant
If className={ classes.classname } , fontSize : '40px' , size= 'large' etc not working then try it inline styling, you can give your height and width size as per required
<OpenInNewIcon style={{ height: '18px', width: '18px' }} />
I hope it will work,
Resize using
fontSize
<Box sx={{ fontSize: '2rem' }}>
<CloseIcon sx={{ fill: 'white', fontSize: 'inherit', mt: 0.375 }} />
</Box>
width orheight
<Box sx={{ width: '15vw' }}>
<CloseIcon sx={{ fill: 'white', width: '100%', height: '100%', mt: 0.375 }} />
</Box>
assuming you using Sass:
.divWithTargetSVG {
.MuiSvgIcon-root {
font-size: Xrem/px;
}
}
This is how I solved my problem with the SVG icon size. I also needed to be smaller when I hit the 768 media query break point.
import { withStyles } from '#material-ui/core/styles';
import { TextField, IconButton } from '#material-ui/core';
import CloseIcon from '#material-ui/icons/Close';
const StyledCloseIcon = withStyles(theme => ({
root: {
fontSize: 35,
[theme.breakpoints.down('768')]: {
fontSize: 19,
}
},
}))(CloseIcon);
use it here like this:
<StyledTextField
size='small'
fullWidth
id="standard-bare"
variant="outlined"
InputProps={{ endAdornment: (<IconButton size='small'><StyledCloseIcon /></IconButton>), }} />
Hope it helps someone. Cheers!
Related
I am practicing React inline animation styling. I have made one toggle button, when user press button first time, I want pop up animated card from left to right. when user press button 2nd time it will close the card from right to left. I want to learn how the animation work inline react styling. Unfortunately I am unable to do that. Seems like React inline styling, transitions and translate does not work to me. This is the animation I want to do it. I shared my code in code-sandbox.
This is my code
import { useState } from "react";
export default function App() {
const [toggle, setToggle] = useState(false);
return (
<>
<button onClick={(): void => setToggle(!toggle)}>toogle button</button>
{toggle && (
<div
style={{
display: "flex",
zIndex: 1,
marginLeft: 170,
background: "red",
width: 200,
height: 300,
opacity: 1,
backgroundColor: "tomato",
transition: "opacity 5s"
}}
>
<p style={{ margin: "0px" }}>animation</p>
</div>
)}
</>
);
}
I don't think that this is a good idea, but here is one solution.
You can control everything.
import "./styles.css";
import { useState } from "react";
export default function App() {
const transitions = ["linear", "ease", "ease-in", "ease-out", "ease-in-out"];
const [opacity, setOpacity] = useState(0);
const [right, setRight] = useState(40);
const speed = 0.5;
return (
<>
<button
onClick={() => {
setOpacity(opacity ? 0 : 1);
setRight(prev => prev === 40 ? 20 : 40);
}}
>
toogle button
</button>
<div
style={{
display: "flex",
zIndex: 1,
marginLeft: 170,
background: "red",
width: 200,
height: 300,
opacity,
backgroundColor: "tomato",
transition: `all ${transitions[1]} ${speed}s`,
transform: `translateX(-${right}%)`
}}
>
<p style={{ margin: "0px" }}>animation</p>
</div>
)
</>
);
}
You could use the inlined styles, but you cannot achieve the desired behavior without the use of CSS or a third party library doing the animations for you.
I would recommend to check out this: https://www.w3schools.com/css/css3_animations.asp
Another problem that I see:
You are displaying the content only as soon as the "toggle" property is true, but for animations you need to have different states in your markup in order to transition to different states of animation.
E.g.
<div className="opening">
<div className="opened">
<div className="closing">
<div className="closed"> (or removed from DOM)
Then you can apply the CSS #keyframes to all different stages using the corresponding CSS selectors.
Or if you don't want to dig into CSS yourself. You can use e.g. this library to do the job: https://react-spring.dev/
I'm trying to override the colour of the bottom navigation icon from material UI [here][1]. This is my css code:
.MuiButtonBase-root{
color: #007A78;
}
.MuiBottomNavigationAction-root{
color: #007A78;
}
.Mui-selected{
color: #007A78;
}
I'm trying to change the default blue colour into my colour (green). However, I only notice the text changes colour, not the icon:
[![enter image description here][2]][2]
I use the elements to see the css and apparently the colour doesn't change for the icon. It's still the same blue colour.
[![enter image description here][3]][3]
Does anyone know how to override this?
[1]: https://mui.com/api/bottom-navigation-action/
[2]: https://i.stack.imgur.com/cG9DW.png
[3]: https://i.stack.imgur.com/joxTL.png
You can use sx to update the styling of the bottom navigation component from the Material UI. You can style the classes individually to apply different styles based on the UI.
sx={{
"& .MuiBottomNavigationAction-root, .Mui-selected, svg": {
color: "#007A78"
}
}}
to style only the active navigation item, you can target the .Mui-selected class as below
sx={{
"& .Mui-selected, .Mui-selected > svg": {
color: "#007A78"
}
}}
Complete code example
import * as React from "react";
import Box from "#mui/material/Box";
import BottomNavigation from "#mui/material/BottomNavigation";
import BottomNavigationAction from "#mui/material/BottomNavigationAction";
import RestoreIcon from "#mui/icons-material/Restore";
import FavoriteIcon from "#mui/icons-material/Favorite";
import LocationOnIcon from "#mui/icons-material/LocationOn";
export default function SimpleBottomNavigation() {
const [value, setValue] = React.useState(0);
return (
<Box sx={{ width: 500 }}>
<BottomNavigation
showLabels
value={value}
onChange={(event, newValue) => {
setValue(newValue);
}}
sx={{
"& .MuiBottomNavigationAction-root, .Mui-selected, svg": {
color: "#007A78"
}
}}
>
<BottomNavigationAction label="Recents" icon={<RestoreIcon />} />
<BottomNavigationAction label="Favorites" icon={<FavoriteIcon />} />
<BottomNavigationAction label="Nearby" icon={<LocationOnIcon />} />
</BottomNavigation>
</Box>
);
}
You could use
<paper sx={{ position: 'fixed', bottom: 0, left: 0, right: 0 }} elevation={3}>
if you are trying to make a bottom navigation.
I need some help merging an animation and a transition that occur at different times using react-spring.
When the component is mounted using useSpring I make the component appear, but I would like it so that when the button child is removed the container transitions smoothly upwards. Theres more details in the example.
https://codesandbox.io/s/naughty-dawn-r0e5x
PLEASE HELP :)
I created a solution. There is a new Spring animation mainly for the button, but we can use part of it for the original div. In this case the maxHeight property. So this way you can combine the animations.
import ReactDOM from "react-dom";
import React, { useState } from "react";
import { useSpring, animated } from "react-spring";
function WelcomeMessage() {
const [isStarted, setIsStarted] = useState(false);
const animation1 = useSpring({
right: "1%",
opacity: 1,
from: { right: "-20%", opacity: 0 },
delay: 300
});
const animation2 = useSpring({
opacity: isStarted ? 0 : 1,
maxHeight: isStarted ? 150 : 250,
transform: `translateY(${isStarted ? "-50px" : "0px"})`
});
return (
<animated.div
style={{
backgroundColor: "pink",
position: "fixed",
top: "2%",
right: "1%",
cursor: "default",
borderRadius: 5,
width: "90%",
maxWidth: 400,
...animation1,
maxHeight: animation2.maxHeight
}}
>
<div style={{ padding: "15px 25px" }}>
<span>
This is a toaster notification component. When you click the following
button it should disappear and the pink container's bottom section
should transition upwards when it decreases in height.
</span>
<br />
<br />
{
<animated.button
style={{ width: "100%", fontSize: 48, ...animation2 }}
onClick={() => {
setIsStarted(true);
}}
>
Get Started
</animated.button>
}
</div>
</animated.div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<WelcomeMessage />, rootElement);
Here is the example: https://codesandbox.io/s/green-star-nzfj8
Is this answer your question?
I am working with React-Redux and Material-UI for styling. I have a < Checkbox /> that is on a toolbar. The toolbar's background-color is blue (#295ED9).
I've managed to change the color of the checkbox, when it is checked. I have also changed the color of the outline of the checkbox to white, when it is unchecked.
Problem: I cannot change the background-color / fill-color of the checkbox when it is unchecked. It is always the same color as the toolbar it is on (blue - #295ED9).
I have tried changing the background-color, color, and fill attributes of the < svg > and the < path > to white.
The best result I can get is when I change the < svg > fill attribute to white. Unfortunately, this does not make the checkbox fill with a white background when unchecked.
JSX
<div className="hasBalance">
<FormControlLabel
control={<Checkbox color="primary"/>}
label="Has Balance"
/>
</div>
SCSS
.hasBalance {
grid-area: balance;
.MuiSvgIcon-root {
fill: white;
}
}
Elements in Chrome Inspect Tool
<div class="hasBalance">
<label class="MuiFormControlLabel-root">
<span class="MuiButtonBase-root MuiIconButton-root PrivateSwitchBase-root-143 MuiCheckbox-root MuiCheckbox-colorPrimary MuiIconButton-colorPrimary" aria-disabled="false">
<span class="MuiIconButton-label">
<input class="PrivateSwitchBase-input-146" type="checkbox" data-indeterminate="false" value="">
<svg class="MuiSvgIcon-root" focusable="false" viewBox="0 0 24 24" aria-hidden="true" role="presentation">
<path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"></path>
</svg>
</span>
<span class="MuiTouchRipple-root"></span>
</span>
<span class="MuiTypography-root MuiFormControlLabel-label MuiTypography-body1">Has Balance</span>
</label>
</div>
The goal is to change the background-color / fill-color of the unchecked Material-UI checkbox to white. Thank you.
Below is an approach that seems to work. This uses the ":after" pseudo-element to place a white background behind the SVG.
import React from "react";
import ReactDOM from "react-dom";
import { withStyles } from "#material-ui/core/styles";
import Checkbox from "#material-ui/core/Checkbox";
const WhiteBackgroundCheckbox = withStyles(theme => ({
root: {
color: "red",
"& .MuiIconButton-label": {
position: "relative",
zIndex: 0
},
"&:not($checked) .MuiIconButton-label:after": {
content: '""',
left: 4,
top: 4,
height: 15,
width: 15,
position: "absolute",
backgroundColor: "white",
zIndex: -1
}
},
checked: {}
}))(Checkbox);
function App() {
return (
<div style={{ backgroundColor: "blue" }}>
<WhiteBackgroundCheckbox />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Related question: Change the tick color in MuiCheckbox material UI
MUIv5
Accepted answer doesn't work in MUIv5. MuiIconButton-label doesn't exist in Checkbox anymore and it changed the structure of the component.
For anyone struggling with v5, here's my kinda-hacky solution :
import { Components } from '#mui/material'
const MuiCheckbox: Components['MuiCheckbox'] = {
styleOverrides: {
root: {
'& .MuiSvgIcon-root': {
zIndex: 1,
},
'& .PrivateSwitchBase-input': {
width: 'auto',
height: 'auto',
top: 'auto',
left: 'auto',
opacity: '1',
visibility: 'hidden', // optional
'&::before': {
content: '""',
position: 'absolute',
background: 'white',
height: "100%",
width: "100%",
visibility: "visible" // optional
},
}
},
},
}
It relies on the fact that the <input> element assumes just the right dimensions and position if we reset its size and positioning attributes. That way the solution is resistant to various paddings and size props applied to the root element of the component. AFAIK it shouldn't break anything, but my experience with MUI is not that long.
Note that I have this solution defined as a global styleOverride in my theme's config and I want this custom background to affect checked tick too - mix and match with Ryan's answer for your scenario.
Visibility attributes are optional, they just make sure the input element stays hidden (I set opacity 1 on it, default is 0). Just make sure you remove both if you don't want them.
index.js
import React from 'react'
import TextField from '#material-ui/core/TextField'
import style from './style'
import withStyles from 'hoc/withStyles'
import { connect } from 'react-redux'
class SearchField extends React.Component {
constructor (props) {
super(props)
this.onChange = this.onChange.bind(this)
}
onChange (event) {
const { dispatcher } = this.props
this.props.dispatch(dispatcher(event.target.value))
event.preventDefault()
}
render () {
const { classes, placeholder } = this.props
return (
<TextField
label={placeholder}
placeholder={placeholder}
InputProps={{ classes: { input: classes.resize } }}
className={classes.textField}
margin="normal"
autoFocus={true}
variant="outlined"
onChange={this.onChange}
/>
)
}
}
export default withStyles(style)(connect()(SearchField))
style.js
export default function () {
return {
container: {
display: 'flex',
flexWrap: 'wrap'
},
textField: {
width: 'auto'
},
resize: {
fontSize: 11
}
}
}
https://material-ui.com/api/text-field/
How can I change TextField height? I can't find it in the documentation. When I try to change it directly in CSS it works incorrectly (it looks like this - selected height on the screen 26px).
What should I do?
You can try out adding the size="small" which is mentioned in the Textfield API
<TextField variant="outlined" size="small" / >
The other answer is useful but didn't work for me because if a label is used in an outlined component (as it is in the question) it leaves the label uncentered. If this is your usecase, read on.
The way the <label> component is styled is somewhat idiosyncratic, using position: absolute and transform. I believe it's done this way to make the animation work when you focus the field.
The following worked for me, with the latest material-ui v4 (it should work fine with v3 too).
// height of the TextField
const height = 44
// magic number which must be set appropriately for height
const labelOffset = -6
// get this from your form library, for instance in
// react-final-form it's fieldProps.meta.active
// or provide it yourself - see notes below
const focused = ???
---
<TextField
label="Example"
variant="outlined"
/* styles the wrapper */
style={{ height }}
/* styles the label component */
InputLabelProps={{
style: {
height,
...(!focused && { top: `${labelOffset}px` }),
},
}}
/* styles the input component */
inputProps={{
style: {
height,
padding: '0 14px',
},
}}
/>
Notes
I just used inline styles rather than the withStyles HOC, as this approach just seems simpler to me
The focused variable is required for this solution - you get this with final-form, formik and probably other form libraries. If you're just using a raw TextField, or another form library that doesn't support this, you'll have to hook this up yourself.
The solution relies on a magic number labelOffset to center the label which is coupled to the static height you choose. If you want to edit height, you'll also have to edit labelOffset appropriately.
This solution does not support changing the label font size. You can change the input font size, only if you're fine with there being a mismatch between that and the label. The issue is that the size of the 'notch' that houses the label in the outlined border is calculated in javascript according to a magic number ratio that only works when the label font size is the default. If you set the label font size smaller, the notch will also be too small when the label shows in the border. There's no easy way to override this, short of repeating the entire calculation yourself and setting the width of the notch (the component is fieldset > legend) yourself via CSS. For me this wasn't worth it, as I'm fine with using the default font sizes with a height of 44px.
The component takes a multiline prop which is a boolean. Set this to true, and then set the component's rows prop to a number.
<TextField
multiline={true}
rows={3}
name="Description"
label="Description"
placeholder="Description"
autoComplete="off"
variant="outlined"
value={description}
onChange={e => setDescription(e.target.value)}
/>
You didn't show how you tried to specify the height, but the approach you used for font-size is the right approach.
Here's an example showing two text fields with different heights:
import React from "react";
import ReactDOM from "react-dom";
import TextField from "#material-ui/core/TextField";
import { withStyles } from "#material-ui/core/styles";
const styles = {
input1: {
height: 50
},
input2: {
height: 200,
fontSize: "3em"
}
};
function App(props) {
return (
<div className="App">
<TextField
variant="outlined"
InputProps={{ classes: { input: props.classes.input1 } }}
/>
<TextField
variant="outlined"
InputProps={{ classes: { input: props.classes.input2 } }}
/>
</div>
);
}
const StyledApp = withStyles(styles)(App);
const rootElement = document.getElementById("root");
ReactDOM.render(<StyledApp />, rootElement);
And here is a code sandbox with the same code so you can see it running.
First of all, my heart goes out to any poor soul in this thread who has found themselves fighting against the awkward design of the MUI components. Second, if you're using themes AND the "filled" variant of TextField, this solution might work for you. Using the Chrome Dev Tools, I found success adjusting the height of the divs with the classes "MuiFormControl-root" and "MuiInputBase-root". This is what my code looks like (results may vary):
const theme = createMuiTheme({
overrides: {
MuiFormControl: {
root: {
height: '56px',
},
},
MuiInputBase: {
root: {
height: '56px',
},
},
},
})
<TextField
id="outlined-multiline-static"
label="Multiline"
multiline
fullWidth
defaultValue="Default Value"
inputProps={{
style: {
height: "600px",
},
}}
/>
To make it narrower, set a height, and add a "dense" margin prop on the TextField to keep the label aligned correctly:
<TextField margin="dense" style={{ height: 38 }} />
With material-ui v4+, you have to adjust the input padding and the label position to get what you whant.
<TextField label="Label" variant="outlined" />
Suppose we want the above TextField to be 48px height (it's default size is 56px), we just have to do (56px - 48px) / 2 = 4px and in our css file:
.MuiTextField-root input {
/* 14.5px = 18.5px - 4px (note: 18.5px is the input's default padding top and bottom) */
padding-top: 14.5px;
padding-bottom: 14.5px;
}
.MuiTextField-root label {
top: -4px;
}
.MuiTextField-root label[data-shrink='true'] {
top: 0;
}
For styled-components users, all the above block of code can be defined as Sass mixins that can be re-used throughout the code base
import { css } from 'styled-components'
const muiTextFieldHeight = (height: number) => {
const offset = (56 - height) / 2
return css`
input {
padding-top: calc(18.5px - ${offset}px);
padding-bottom: calc(18.5px - ${offset}px);
}
label {
top: -${offset}px;
}
label[data-shrink='true'] {
top: 0;
}
`
}
Then somewhere in your stylesheet
.MuiTextField-root {
${muiTextFieldHeight(40)} /* set TextField height to 40px */
}
This works with material-ui v3,
<div className="container">
<TextField
label="Full name"
margin="dense"
variant="outlined"
autoFocus
/>
</div>
.css
.container input {
height: 36px;
padding: 0px 14px;
}
.container label {
height: 36px;
top: -6px;
}
.container label[data-shrink="true"] {
top: 0;
}
https://codesandbox.io/s/elated-kilby-9s3ge
With React and "#mui/material": "^5.2.2",
import * as React from 'react';
import TextField from '#mui/material/TextField';
export default function BasicTextFields() {
return (
<TextField
label="Outlined"
variant="outlined"
InputLabelProps={{
style: {
fontSize: 14,
backgroundColor: '#FFF',
paddingLeft: 4,
paddingRight: 4,
color: '#383838',
},
}}
inputProps={{
style: {
fontSize: 14,
height: 40,
width: 272,
padding: '0 14px',
fontWeight: 'bold'
},
}}
/>
);
}
CSS
.MuiTextField-root{
border: 1px solid $BORDER_COLOR_2;
border-radius: 6px;
height: 40px;
box-shadow: 0px 2px 3px $BOX_SHADOW_1;
color: $TEXT_COLOR_3;
font-size: 14px;
font-weight: bold;
}
.MuiTextField-root label {
top: -6px;
}
.MuiTextField-root label[data-shrink='true'] {
top: 0;
}
Changing the height is simple, can be achieved using
InputProps={{style: { fontSize: '1.8rem', height: 70 },
But that isn't enough, because the label(placeholder in this case) will not be centered.
Label can be centered using:
sx={{'.MuiFormLabel-root[data-shrink=false]': { top: <put desired value here>} }}