Checkbox label full width - css

I have a <Checkbox> component wrapped in a <FormControlLabel>. They are placed inside a container like this:
<FormGroup row={true} key={option.id}>
<FormControlLabel
className="ContractOfferOptionsSelector__option"
key={option.id}
control={
<Checkbox checked={option.selected} onChange={this.handleChange} value={String(option.id)} />
}
label={this.renderLabel(option)}
/>
</FormGroup>
private renderLabel(option: ISelectableOption) {
return (
<div className="ContractOfferOptionsSelector__option">
<span className="ContractOfferOptionsSelector__option__title">
<span className="ContractOfferOptionsSelector__option__title__abbreviation">{option.abbreviation}</span>
<span className="ContractOfferOptionsSelector__option__title__description">{option.description}</span>
</span>
<span className="ContractOfferOptionsSelector__option__price">
{`${formatCurrency(option.price.priceInclVat)} ${t(option.price.currency)}`}
</span>
</div>
)
}
The label renders as a <span> and 'tightly' wraps the content (so it doesn't take full width of the container). I have put multiple elements inside the label (price, title...) and want to make the label take full width, so that the elements space out across full width.
I tried .ContractOfferOptionsSelector__option {width: 100%;} but it doesn't work because the parent is also a <span>? with a dynamically generated class name...
How can I control the width of the label in material-ui?

<span> has a default inline display property.
Inline elements:
- Respect left & right margins and padding, but not top and bottom
- Cannot have a width and height set
Try to set display: inline-block to your <span> and add position: relative to the FormGroup container.

Solution
(tested with MUI v4)
import React from "react";
import { Checkbox, FormControl, FormControlLabel, FormGroup, makeStyles, TextField } from "#material-ui/core";
export default function App() {
const classes = useStyles();
return (
<FormControl fullWidth>
<FormGroup>
<FormControlLabel
classes={{
label: classes.fullWidth
}}
control={<Checkbox />}
label={<TextField label="Full width" defaultValue="Working" variant="outlined" fullWidth />}
/>
</FormGroup>
</FormControl>
);
}
const useStyles = makeStyles((theme) => ({
fullWidth: {
width: "100%",
},
}));
Full code on codesandbox.
Explanation
As you pointed out in your question, both the label and the control components become span elements inside FormControlLabel, with some default style as well.
To force the label to cover full width, you need to:
Toggle on the fullWidth prop for the FormControl;
Override the label CSS class in FormControlLabel to set its width: 100%

Related

Make the width of the dropdown list different from the width of the dropdown button

I would like to realize a dropdown, where the width of the dropdown button is not necessarily equal to the width of the dropdown list.
I know that we can use style={{ minWidth: '200px' }} to control the width of the dropdown button and dropdown list. Now, I would like to make the width of the dropdown list 500px.
I tried to set .fui-Listbox { width: 500px } in the stylesheet, but it did not work.
Does anyone know how to do that?
StackBlitz: https://stackblitz.com/edit/react-ts-cejuzs?file=App.tsx,style.css,index.html
import {
FluentProvider,
webLightTheme,
makeStyles,
shorthands,
} from '#fluentui/react-components';
import {
Dropdown,
Option,
DropdownProps,
} from '#fluentui/react-components/unstable';
import { TextField } from '#fluentui/react';
import * as React from 'react';
import './style.css';
export default class Grouped extends React.Component<{}, {}> {
land = ['Cat', 'Dog', 'Ferret', 'Hamster'];
render() {
return (
<FluentProvider
className="fluent-provider"
style={{ display: 'flex' }}
theme={webLightTheme}
>
<Dropdown
className="drop-down"
style={{ minWidth: '200px' }}
placeholder="Select an animal"
>
{this.land.map((option) => (
<Option key={option}>{option}</Option>
))}
</Dropdown>
</FluentProvider>
);
}
}
Edit 1: Following pier farrugia's answer, I tried to use .fui-Listbox { width: 500px !important; }. It did make the width of the dropdown list 500px, however it impacted all the dropdowns in the project, which is not what I want. I tried to add classes and wrote selectors such as .drop-down .fui-Listbox { width: '500px' !important; } and .drop-down-2 .fui-Listbox { width: '100%' !important; }, but it did not work. I guess it's because under the mode of dropdown, .fui-Listbox is not a child class of drop-down-2 or .fluent-provider-2. Does anyone know how to properly write the selectors to limit the impact only to the dropdown I target?
https://stackblitz.com/edit/react-ts-51hiro?file=App.tsx,style.css,index.html
in the code you have :
<Dropdown
className="drop-down"
style={{ width: '100px' }}
placeholder="Select an animal"
>
Your style 100px is generated dynamically.
Change in style even with !important is not working.
Modify the the line
style={{ width: '100px' }}
to
style={{ width: '500px' }}
To change only the width of the dropdown list, you have to use the style or the className tag for that specific dropdown slot (listbox):
<Dropdown
className="drop-down"
style={{ minWidth: '200px' }}
placeholder="Select an animal"
listbox={{style: {width: "500px"}}}
>
{this.land.map((option) => (
<Option key={option}>{option}</Option>
))}
</Dropdown>
or if you want to keep using your stylesheet
<Dropdown
className="drop-down"
style={{ minWidth: '200px' }}
placeholder="Select an animal"
listbox={{className: "custom-dropdown-width"}}
>
{this.land.map((option) => (
<Option key={option}>{option}</Option>
))}
</Dropdown>
and in your stylesheet
.custom-dropdown-width {
width: '500px' !important;
}

How to use percentage height for CardContent inside a styled Card?

I currently have a custom styled Card that simply has default width/height values. I use CardMedia inside that card, and I want the CardContent to fill up the remaining space available on that Card, but if I just use height: 100% then the CardContent's height is the same as the Card itself, without taking the CardMedia's height into consideration.
How do I make CardContent fill up the remaining space available on a Card?
const CustomCourseCard = styled(Card)(({ theme }) => ({
width: "20rem",
height: "25rem",
}));
export const CourseCard = () => {
return (
<Card>
<CardMedia
component="img"
src="https://res.cloudinary.com/dety84pbu/image/upload/v1598465568/nebula_cat_djkt9r.jpg"
height="200px"
/>
<CardContent sx={{ height: "100%" }}>
<Stack justifyContent="space-between">
<Typography>Title</Typography>
<Typography>Content</Typography>
</Stack>
</CardContent>
</Card>
);
};

How do I make material ui container have full width and height?

I am trying to wrap a page in a React project in a material UI container but it squeezes in all my content with these weird margins. Here is what it looks like:
But I want it to look like this with full width:
Haven't been able to find any other resources explaining how to change the width of the container. Does anyone have any workarounds? I tried adjusting the width of the container to be 100vw but it was unresponsive to my CSS. Here is my code:
////BUY PAGE
import React from 'react';
import Container from '#mui/material/Container';
import AppBar from '../../components/AppBar/AppBar';
import Footer from '../../components/Footer/Footer';
import './Buy.css';
const Buy = () => {
return (
<Container>
<AppBar />
<Footer />
</Container>
);
};
export default Buy;
////CSS
.buy-container {
overflow-y: hidden;
width: 100vw;
}
You should be able to get the results you're looking for by setting the maxWidth property of Container to false e.g:
<Container maxWidth={false}>
<AppBar />
<Footer />
</Container>
Edit:
The maxWidth property determines the max-width of the container. The container width grows with the size of the screen. By setting it to false you can disable the maxWidth property.
https://mui.com/api/container/
You will need to add maxWidth={false} and disableGutters properties to the <Container/> component. Additionally, you should include the <CssBaseline/> component to reset the browser's CSS.
Example:
<>
<CssBaseline />
<Container maxWidth={false} disableGutters>
{children}
</Container>
</>
Container API
Name
Type
Default
Description
maxWidth
'xs', 'sm', 'md', 'lg', 'xl', false, string
Determine the max-width of the container. The container width grows with the size of the screen. Set to false to disable maxWidth.
disableGutters
bool
false
If true, the left and right padding is removed.
You should avoid to set the custom container width until changing the breakpoints.
Otherwise, you can use a custom div element or Box component.
// makeStyles
const useStyles = makeStyles(() => ({
root: {
height: '100%',
overflow: 'hidden',
width: '100%'
},
}));
// styled
const LayoutContainer = styled('div')(() => ({
height: '100%',
overflow: 'hidden',
width: '100%'
}));
I'd take a look at global css variables to overwrite the standard (see here):
The material docs suggest this way or using styling overrides which may be another option for you.
.MuiContainer-root {
width: 100vw;
padding-left: 0;
padding-right: 0;
}
FYI - I got the global css name from the Container portion of the docs under "root", in case you've not seen it.
I would use the <Container> within <Box>/<Appbar> that has the background color e.g:
<Box sx={{ bgcolor: 'black'}}>
<Container>
My content
</Container>
</Box>
minHeight: '100%' worked for me in that kind of situation

How to align a Material UI Button and TextField on the same line, at same height?

I'm trying to get a <Button> from the Material UI library to a) sit at same height as the <TextField> next to it; and b) have it be aligned with that same field.
Both the <Button> and the <TextField> are each inside their own <Grid> component (with a container wrapping them).
The container <Grid> has the prop alignItems="center", which produces this result:
It's here I'm running into difficult trying to get the height of the <Button> to match that of the input field. This must be a relatively common requirement - is there a simple way of achieving this?
Given that you have each of your element in a <Grid> component themselves, this should work:
https://codesandbox.io/s/material-ui-playground-forked-1yymw?file=/app.jsx
Use container={true} for Grid to set it as a flex container. Aside from that, you can always leverage makeStyles to generally customize the components' style
MUI Grid container prop
If true, the component will have the flex container behavior.
const useStyles = makeStyles({
fullHeightButton: {
height: "100%"
}
});
function App() {
const classes = useStyles();
return (
<React.Fragment>
<Grid container={true}>
<TextField variant="outlined"/>
<Button variant="contained" color="primary">+</Button>
</Grid>
<br/>
<Grid container={true}>
<Grid><TextField variant="outlined"/></Grid>
<Grid><Button classes={{root: classes.fullHeightButton}} variant="contained" color="primary">+</Button></Grid>
</Grid>
</React.Fragment>
);
}
ReactDOM.render(<App/>, document.getElementById("test"));
<body>
<div id="test"></div>
<script src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<script src="https://unpkg.com/#material-ui/core#latest/umd/material-ui.development.js"></script>
<script type="text/babel">
const { Button, Grid, makeStyles, TextField } = MaterialUI;
</script>
</body>
In my case, I had two buttons that sandwiched a TextField, where the spacing between the first button and the textfield was wrong as shown:
Buttons before code addition
My code was:
<CardActions className='cardactions'>
<Button variant='contained' color='error'> - </Button>
<TextField id='outlined-basic' variant='outlined' size='small' type='number' label='Enter Quantity'/>
<Button variant='contained' color='success'>+</Button>
</CardActions>
Adding sx={{ marginRight:1}} to the first button corrected the issue.
Buttons after code addition
Code after addition:
<CardActions className='cardactions'>
<Button variant='contained' color='error' sx={{ marginRight:1}}> - </Button>
<TextField id='outlined-basic' variant='outlined' size='small' type='number' label='Enter Quantity'/>
<Button variant='contained' color='success'>+</Button>
</CardActions>

Material UI make 2 elements the same height

I have the following code:
<div className="center">
<TextField
variant="outlined"
className="manualUserFollowTxt"
required
id="manualUserFollowTxt"
label="Username"
name="username"
autoComplete="username"
autoFocus
/>
<Button variant="contained" color="primary" className="manualUserFollowButton"
onClick={(e) => this.followButtonClick(e, document.getElementById("manualUserFollowTxt").value)}
>
Follow
</Button>
</div>
Which basically results in:
what I have
What I want is to have the TextField and the Button be the same height with a little space in between and sitting on one line, preferably in the middle. Something like:
what I want
How can I achieve this??
In order to make the TextField and Button the same height and aligned, you can CSS Flexbox on the parent div.
Set the display to flex, and flex-direction to row.
In order to apply spacing between the TextField and Button, you can apply margin-right to the TextField (here I used material-ui styling):
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import TextField from '#material-ui/core/TextField';
import Button from '#material-ui/core/Button';
const useStyles = makeStyles(theme => ({
textField: {
marginRight: theme.spacing(2),
},
}));
export default function TextFieldDemo() {
const classes = useStyles();
return (
<div style={{display: 'flex', flexDirection: 'row'}}>
<TextField
variant="outlined"
className={classes.textField}
required
id="manualUserFollowTxt"
label="Username"
name="username"
autoComplete="username"
autoFocus
/>
<Button variant="contained" color="primary" className="manualUserFollowButton"
onClick={(e) => this.followButtonClick(e, document.getElementById("manualUserFollowTxt").value)}
>
Follow
</Button>
</div>
);
}

Resources