Align Card Buttons on bottom Material UI - css

I am developing an app in ReactJS and i'm using the following: MaterialUI (for react) and React Flexbox.
The problem i'm having is trying to position the card buttons on bottom (the problem that seems to have spammed the internet in different frameworks).
I am using the card from here -> https://material-ui.com/demos/cards/
I've tried pretty much everything i could think of from align-items to align-self and different display types. I might be missing something here since i usually work with Bootstrap so i hope a CSS Master can help me out. I'll attach the pic below for ref.
Also for ref here's how my code looks in react( ApiPosts is my cards component) ->
<Grid container>
<Grid item xs={12}>
<Paper className={classes.paper}>
<Row className="rowSpacer">
<Col xs>
<Typography variant="title" align="center" color="textPrimary" gutterBottom>
Posts are below
</Typography>
</Col>
</Row>
<Divider />
<ApiPosts />
</Paper>
</Grid>
</Grid>
And finally my cards are wrapped in <Row around="xs"> (4 posts in a row) and each card in a col <Col xs >
Thanks in advance!
Edit: Solved thanks to Ivan's answer.Here's the code in case anyway needs it (working on Material-UI Cards).
.portCardCl {
display: flex;
flex-direction: column;
height:100%;
}
.portBodyCl {
display: flex;
flex: 1 0 auto;
align-items: flex-end;
justify-content: center;
flex-direction: column;
}
.portButCl{
display: flex;
justify-content: flex-start;
}
portCardCl goes on the first <Card>, portBodyCl goes on <CardActionArea> and finally portButCl goes on <CardActions>

Here is example with css-grid.
const {
Button,
createMuiTheme,
CssBaseline,
MuiThemeProvider,
Typography,
Paper,
withStyles,
} = window['material-ui'];
const styles = theme => ({
root: {
display: "grid",
gridTemplateColumns: "repeat(4, 1fr)",
gridGap: "24px",
},
card: {
display: "grid",
gridTemplateRows: "1fr auto",
gridGap: "8px",
minHeight: 280,
backgroundImage: `url(https://via.placeholder.com/100x200)`,
backgroundSize: "cover"
},
body: {
alignSelf: "end",
textAlign: "center"
},
actions: {
display: "flex",
justifyContent: "space-between"
}
});
const Grid = withStyles(styles)(
class Grid extends React.Component {
render () {
const { classes } = this.props;
const cards = [1, 2, 3, 4];
return (
<div className={classes.root}>
{cards.map(c => (
<Paper key={c} className={classes.card}>
<div className={classes.body}>
<Typography variant="subheading">
Test Image
</Typography>
<Typography variant="caption">
Small help text
</Typography>
</div>
<div className={classes.actions}>
<Button>Left</Button>
<Button color="primary">Right</Button>
</div>
</Paper>
))}
</div>
)
}
}
)
const theme = createMuiTheme();
ReactDOM.render((
<MuiThemeProvider theme={theme}>
<Grid />
</MuiThemeProvider>
), document.querySelector("#root"))
<script src="https://unpkg.com/react#latest/umd/react.development.js" crossorigin="anonymous"></script>
<script src="https://unpkg.com/react-dom#latest/umd/react-dom.development.js" crossorigin="anonymous"></script>
<script src="https://unpkg.com/#material-ui/core/umd/material-ui.development.js" crossorigin="anonymous"></script>
<script src="https://unpkg.com/babel-standalone#latest/babel.min.js" crossorigin="anonymous"></script>
<div id="root"></div>
Here is example of card with flex using only
.card {
padding: 24px;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .13);
background: skyblue;
border-radius: 4px;
font-family: "Helvetica", sans-serif;
display: flex;
flex-direction: column;
height: 280px;
width: 160px;
}
.card__body {
display: flex;
flex: 1 0 auto;
align-items: flex-end;
justify-content: center;
}
.card__actions {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 16px;
}
<div class="card">
<div class="card__body">
Test Text
</div>
<div class="card__actions">
<button>Left</button>
<button>Right</button>
</div>
</div>

Related

Styling Grid to have more elements than text

I have grid from material UI:
Item element
const Item = styled(Paper)(({theme}) => ({
...theme.typography.body2,
padding: theme.spacing(2),
textAlign: 'center',
color: "black",
}));
Structure
<div className="wrapper">
<Typography variant="h3" component="h3">
List of friends
</Typography>
<div className="friends">
<Grid container
direction="row"
rowSpacing={1}
spacing={{xs: 2, md: 3}} columns={{xs: 4, sm: 8, md: 12}}
alignItems="center"
justifyContent="center"
>
{
friends.map((friend, i) => {
return <Grid item xs={4} sm={6} md={6} mt={5}>
<Item className="item"><span>{i}</span>{friend.name}</Item>
</Grid>
})
}
</Grid>
</div>
</div>
With css:
.wrapper{
width: 100%;
position: relative;
align-items: center;
display: flex;
flex-direction: column;
background:#eaeaea
}
.friends{
position: relative;
width: 75%;
}
It looks like this:
However, i would like the number of friend, to be on the left, and highlighted like:
However, how to stile the <span> element to do this? The when i style span to be
span{
position: absolute;
left: 0
width:25%;
height: 100%
}
Then the span is somewhere else, as the material ui uses lot of styling that makes this hell.
when i change it to:
{
countries.map((friend, i) => {
return <Grid item xs={4} sm={6} md={6} mt={5} >
<span> i </span>
<Item className="item">{friend.name}</Item>
</Grid>
})
}
I would need to make adjustments to the Grid elements, adding position relative and such, but im not sure how this would work with responsivity.
Is there simple way to do this?
Or is there any other component i can use instead of Item(Paper) element?
Thanks for help!
You can use display: grid on the Paper element, like so:
<Paper
sx={{
display: 'grid',
grid: 'auto / 25% 75%',
height: 50,
'& > div': {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100%',
},
}}
>
<Box>1</Box>
<Box>Name</Box>
</Paper>
Alternatively, you can do it with flex: 1 and flex: 3, but I think the grid method is easier to set up, since all the logic is in one line.

How to show less number of pages on mobile view in Pagination?

Problem
Need to show less number of pages in mobile view so that it can be aligned with heading (My Orders) in the same line.
Library
material-ui/pagination
Progress
Able to remove Next and Previous content in the mobile view but neither able to find any out-of-the-box prop(s) nor any CSS to reduce number of pages in mobile view
Web view
Mobile View
Code
CSS
#media (min-width: 501px) {
.MuiPagination-root {
.MuiPagination-ul {
flex-wrap: nowrap;
li {
&:first-child {
flex-basis: 100%;
display: flex;
justify-content: flex-start;
align-items: center;
> button::before {
margin-right: 10px;
content: "Previous ";
}
}
&:last-child {
flex-basis: 100%;
display: flex;
justify-content: flex-end;
align-items: center;
> button::after {
margin-left: 10px;
margin-right: 20px;
content: " Next";
}
}
}
}
}
Custom Component
import React, { useState } from "react";
import PropTypes from "prop-types";
import Pagination from '#material-ui/lab/Pagination';
export const CustomPagination = ({ onChange, totalRecords, currentPage, className, shape }) => {
return (
<Pagination
count={totalRecords}
shape={shape}
className={className}
onChange={onChange}
page={currentPage}
/>
)
};
CustomPagination.propTypes = {
paginationLength: PropTypes.number,
selectPage: PropTypes.func,
activePage: PropTypes.number,
};
One of the solutions I came up with is wrapping the component pagination inside a Box then changing its size depending on the view :
export function Test() {
return;
<>
<Box sx={{ display: { xs: "none", md: "block" } }}>
<Pagination
/>
</Box>
<Box sx={{ display: { xs: "block", md: "none" } }}>
<Pagination
size="small"
/>
</Box>
</>;
}
</Box>

Why does centring my div stop it taking it taking up the max amount of width available?

I am having an issue centring a div with elements using justify-content: space-between;. The child element fills the max-width of the container(900px) prior to either putting a margin auto or justify-content: center; on the parent object. once these styles are added to centre the container the elements inside are crushed to the min-width possible. What's the solution to this because I still would like to have the content inside the container shrink to the screen width?
The parent div using styled-components to have the following styles:
import styled from 'styled-components'
import { ACCOUNT_MAX_WIDTH, UNIT_8 } from '../../../components/_core/grid'
export const AccountMaxWidth = styled.div`
max-width: ${ACCOUNT_MAX_WIDTH};
align-self: stretch;
display: flex;
flex-direction: column;
flex: 1;
padding: ${UNIT_8};
padding-top: 0;
//toggling this on centres the div but crushes the div.
margin: auto;
`
Styles of the child div:
import styled from 'styled-components'
import { COLOUR } from '../../../components/_core/colours'
import { UNIT_1, UNIT_3, UNIT_4 } from '../../../components/_core/grid'
export const PreferencesWrapper = styled.div`
display: flex;
flex-direction: column;
> h2 {
padding: ${UNIT_4} 0;
color: ${COLOUR.primary.blue_slate};
}
`
export const SwitchHeadContainer = styled.div`
display: flex;
flex-direction: row;
justify-content: space-between;
padding: ${UNIT_1} 0;
> svg {
margin: auto 0;
margin-right: ${UNIT_4};
}
> h4 {
margin: auto 0;
}
`
export const SwitchContainer = styled.div`
display: flex;
flex-direction: column;
> label {
flex-wrap: wrap;
margin: ${UNIT_3} 0;
padding: 0 ${UNIT_1};
justify-content: space-between;
}
Here is the tsx file(this is imported and nested within the AccountMaxWidth styled div):
import { Divider } from '#material-ui/core'
import * as React from 'react'
import { useTranslation } from 'react-i18next'
import { Switch } from '../../../components/_atoms/Switch'
import { COLOUR } from '../../../components/_core/colours'
import { MailIcon } from '../../../components/_core/icons/Mail'
import { Medium, Small2X } from '../../../components/_core/Typography'
import {
PreferencesWrapper,
SwitchContainer,
SwitchHeadContainer,
} from './index.styles'
export const Preferences = () => {
const { t } = useTranslation()
return (
<PreferencesWrapper>
<Medium>{t('account.preferences.heading')}</Medium>
<SwitchContainer>
<SwitchHeadContainer>
<Small2X>{t('account.preferences.notifications.subheading')}</Small2X>
<MailIcon fill={COLOUR.primary.blue_slate} variant="line" />
</SwitchHeadContainer>
</SwitchContainer>
<SwitchContainer>
<Divider variant="fullWidth" />
<Switch
label={t('account.preferences.notifications.protectionStatus')}
isChecked={true}
onToggle={() => null}
/>
</SwitchContainer>
<SwitchContainer>
<Divider variant="fullWidth" />
<Switch
label={t('account.preferences.notifications.highThreat')}
isChecked={true}
onToggle={() => null}
/>
</SwitchContainer>
<SwitchContainer>
<Divider variant="fullWidth" />
<Switch
label={t('account.preferences.notifications.mediumThreat')}
isChecked={true}
onToggle={() => null}
/>
</SwitchContainer>
<SwitchContainer>
<Divider variant="fullWidth" />
<Switch
label={t('account.preferences.notifications.lowThreat')}
isChecked={true}
onToggle={() => null}
/>
</SwitchContainer>
<SwitchContainer>
<Divider variant="fullWidth" />
<Switch
label={t('account.preferences.notifications.news')}
isChecked={true}
onToggle={() => null}
/>
</SwitchContainer>
<SwitchContainer>
<Divider variant="fullWidth" />
<Switch
label={t('account.preferences.notifications.account.heading')}
isChecked={true}
onToggle={() => null}
/>
</SwitchContainer>
</PreferencesWrapper>
)
}
[Image One][1]
Here is an image where the div is centred using margin auto or align-self centre as you can see the div is crushed.
[Image Two][2]
Here is an image of how the div looks before centre aligning and how I'd like it to look after centre alignment.
The only difference between the two images is a margin auto
[1]: http://imgur.com/hgJUU0a
[2]: http://imgur.com/W2gyAzs
I may need more clarification on your question, but justify-content: space-between; should still keep you element center, especially if it's the only element in its parent, without any sibling elements. To center its own children, I would add the centering properties to that div, like in this code:
Also, make sure that the parent element of the parent is also display: flex or that align-self will not do anything. And for a horizontal stretch, you may actually want to use justify-content: stretch.
.parentElement {
display: flex;
justify-content: space-between;
}
.parentElement > .childElement {
display: flex;
justify-content: center;
flex: 1;
}
I'd like to assist further, but I'm still having a difficult time fully understanding your question. Would you mind adding a working snippet to your ticket that demonstrates the issue that needs to be fixed so I can adjust a copy of your code directly? Thanks!
Try giving the PreferencesWrapper a min-width or width: 100%.
Hope you are doing well, you have not shared any codesandbox to test out the changes on your code and provide you the solution, but what seems to be the problem on the surface is max-width. Please change the styles accordingly.
export const AccountMaxWidth = styled.div`
min-width: ${ACCOUNT_MAX_WIDTH};
align-self: stretch;
display: flex;
flex-direction: column;
flex: 1;
padding: ${UNIT_8};
padding-top: 0;

Center content and make their position adjustable

I'm new to react and css.
My goal here is to center my 3 switches and the name of them in the center of my page. Then I would like the 3 switches button to adjust their position automatically no matter the length of the text on its left.
Here is what I have for the moment.
This is the switch button + text. I made a style to align the text with the middle of the switch icon. I tried the verticalAlign: "middle" but it the text went at the bottom position.
import React, { useState } from "react";
import Switch from "react-switch";
const SwitchMode = ({text}) => {
const [checked, setChecked] = useState(false)
const handleChange = StateCheck => {
setChecked(StateCheck)
}
return(
<div className="switch-position">
<label>
<span style={{display: "inline-flex", verticalAlign: '50%', marginRight: '4%'}}>{text}</span>
<Switch
onChange={handleChange}
checked={checked}
className="react-switch"
/>
</label>
</div>
)
}
export default SwitchMode
And this is the css I've made for the moment
body {
margin: 0;
}
.image-position {
display: flex;
justify-content: center;
width: 100%;
margin-top: 5%;
height: auto;
}
.service-position {
display: flex;
flex-direction: column;
margin-top: 5%;
}
.switch-position {
display: inline;
justify-content: center;
width: 100%;
margin-top: 1%;
}
in this file I create my switch button, apply the css and give them a name.
import React from 'react';
import './index.css';
import ReactRoundedImage from "react-rounded-image";
import Img from './images/Diamond.png'
import SwitchMode from './Switch';
const Profile = () => {
return(
<div>
<div className='image-position'>
<ReactRoundedImage image={Img} roundedSize="0" imageWidth="150" imageHeight="150" />
</div>
<div className='service-position'>
<SwitchMode text="Discord"/>
<SwitchMode text="Google"/>
<SwitchMode text="FEJZIOFZEJ"/>
</div>
</div>
)
}
export default Profile
this is the actual result
You can do something like this:
body {
margin: 0;
}
.image-position {
display: flex;
justify-content: center;
width: 100%;
margin-top: 5%;
height: auto;
}
.service-position {
display: flex;
justify-content: center;
flex-direction: row;
margin-top: 5%;
}
.switch-position {
text-align: center;
width: 100px;
}
and change your SwitchMode component to this:
const SwitchMode = ({ text }) => {
const [checked, setChecked] = useState(false);
const handleChange = (StateCheck) => {
setChecked(StateCheck);
};
return (
<div className="switch-position">
<label>
<span>{text}</span>
<Switch
onChange={handleChange}
checked={checked}
className="react-switch"
/>
</label>
</div>
);
};
The main things I did was set justify-content: center and flex-direction: row on .service-position. To make sure the .switch-position items displayed in a row and were centered.
For centering the text next to the switch button I used text-align: center and to make sure the text is displayed above the switch button I set a fixed with on .switch-position.
Sandbox Example

How do align content to the center in flexbox

I have a item that i want to be align to the middle and one to the bottom.
I want the logo image in the center, but I can't figure out how to do it.
import React, { Component } from 'react';
import { Container, Content, Text, Button, View } from 'native-base';
import { StyleSheet, Image } from 'react-native'
export default class WelcomeScreen extends Component {
render() {
return (
<Container>
<Content contentContainerStyle={styles.container}>
<View style={styles.imgContainer}>
<Image
source={require('../../assets/images/logos/logo.png')}
/>
</View>
<View style={styles.btnContainer}>
<Button block primary onPress={() => this.props.navigation.navigate('Signin')} rounded>
<Text>Sign in</Text>
</Button>
<Button block light style={{ marginTop: 15 }} onPress={() => this.props.navigation.navigate('Signup')} rounded>
<Text>Sign up</Text>
</Button>
</View>
</Content>
</Container>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
imgContainer: {
flex: 1,
},
btnContainer: {
width: 300,
}
})
Try this
imgContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center'
}
Here's an HTML CSS only example for you that you can easily tweak to solve your problem.
body {
margin: 0;
}
#main {
display: flex;
flex-direction: column;
height: 100vh;
justify-content: space-between;
}
.container {
align-items: middle;
margin: 0 auto;
align-self: middle;
width: 300px;
height: 80px;
background-color: steelblue;
vertical-align: afar;
}
<div id="main">
<div class="container">
abc
</div>
<div class="container">
xyz
</div>
</div>
The trick lies in the following CSS properties:
flex-direction: column
justify-content: space-between
if you want the image to align center in the screen except for the button height, you can use the following code, and replace the view in ImageContainer to Image
render() {
return (
<Container>
<View
style={styles.imgContainer}>
<View style={{backgroundColor:'red',height:50,width:50}} />
</View>
<Content contentContainerStyle={styles.container}>
<View style={styles.btnContainer}>
<Button block primary onPress={() => this.props.navigation.navigate('Signin')} rounded>
<Text>Sign in</Text>
</Button>
<Button block light style={{ marginTop: 15 }} onPress={() => this.props.navigation.navigate('Signup')} rounded>
<Text>Sign up</Text>
</Button>
</View>
</Content>
</Container>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'flex-end'
},
imgContainer: {
position:'absolute',
justifyContent:'center',
alignItems:'center',
height:Dimensions.get('window').height-40,
width:Dimensions.get('window').width,
flex: 1,
},
btnContainer: {
height:200,
width: 300,
alignItems:'center',
justifyContent: 'flex-end',
marginBottom:20
}
})

Resources