Is it possible to use styled-component to create a wrapper container containing React Bootstrap's Modal component in order to make the modal be both horizontally and vertically aligned?
Tried creating CenteredModal container as shown, but the .modal element does not appear to have the new styles applied to it.
import { Modal } from "react-bootstrap";
import styled from 'styled-components';
const CenteredModal = styled.div`
& .modal {
display: flex !important;
align-items: center;
}
`
interface MyModalProps {
isOpen: boolean,
onHide: () => void
}
export default function MyModal({
isOpen = false,
onHide,
}: MyModalProps) {
return (
<CenteredModal>
<Modal show={isOpen} onHide={onHide}>
<h1>Hello</h1>
</Modal>
</CenteredModal>
)
}
Because Modal of react-bootstrap isn't render inside CenteredModal, so your style can't affect it (You can open the browser developer tool to see, it should be rendered at the bottom of the html body not in the CenteredModal div element).
I saw react-bootstrap is already provides a centering method, is this what you want? you can take a look https://react-bootstrap.github.io/components/modal/
why not use centered prop ?
example :
<Modal
size="lg"
centered
>
Your new container just needs a little tweaking:
const CenteredModal = styled.div`
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
`
You can use this syntax:
import { Modal } from "react-bootstrap";
import styled from 'styled-components';
const CenteredModal = styled(Modal)`
display: flex !important;
align-items: center;
`;
Related
I'm using React and trying to fetch some of my anime into the home banner using Swiper
I don't know why when I refresh my page, it'll only render at half of the swiper.
Here's how it display:
However, if I press the next or back button, it'll display normally again.
Here's my code in my Home Component:
import { useState, useEffect } from "react"
import ReactHlsPlayer from 'react-hls-player';
import './home.css'
import { supabase } from '../../supabaseClient'
import { Swiper, SwiperSlide } from 'swiper/react'
import SwiperCore, { Pagination,Navigation } from 'swiper';
import 'swiper/css'
SwiperCore.use([Pagination,Navigation]);
function Home(){
useEffect(async ()=>{
fetchAnime()
}, [])
const [animeDetail, setAnimeDetail] = useState([])
async function fetchAnime() {
const { data } = await supabase
.from ('anime')
.select ()
setAnimeDetail(data)
}
return (
<>
<div className="spacer">
</div>
<div className="home-section">
<h2>Home Page</h2>
<Swiper
centeredSlides={true}
slidesPerView={7}
spaceBetween={10}
loop={true}
pagination={false}
navigation={true} className="mySwiper">
{animeDetail.map((element, i)=>
(
<SwiperSlide key = {i}><img src={element.anime_image}/></SwiperSlide>
)
)}
</Swiper>
</div>
</>
)
}
export default Home
And here's my Home CSS, sorry if it's a bit messy, I'm still trying it here and there, but I'm stuck.
.swiper {
width: 100%;
height: 100%;
margin-left: auto;
margin-right: auto;
}
.swiper-wrapper{
width: 100%
}
.swiper-slide {
text-align: center;
font-size: 18px;
display: flex;
justify-content: center;
align-items: center;
max-width: 280px;
}
.swiper-slide img {
display: block;
box-sizing: border-box;
border: none;
max-height: 350px;
min-height: 350px;
-o-object-fit: cover;
object-fit: cover;
transition: all .3s ease;
opacity: 0.5
}
.swiper-slide-active {
transform: scale(1.2);
z-index: 2
}
.swiper-slide-active img{
transition: all .3 ease;
opacity: 1
}
And if someone figures it out, please help me a bit, I tried to whenever the item in the middle is in active, it'll pop out bigger, but I can't do it with transform: scale(number) - I have tried it (It does get bigger when it's active but it doesn't display bigger at the height, I haven't figured it out some ways at the moment)
you have to set the initialSlide prop on the Swiper element to an index of the slide in the middle. so that the slider starts from there.
Also in this case, you can set the centeredSlides prop to true as the active slide remains in the middle.
Here's a possible fix for your issue and for everyone else that comes here looking for answers.
Use conditional rendering of the Swiper component, something like this:
{animeDetail.length>0 && <Swiper
centeredSlides={true}
slidesPerView={7}
spaceBetween={10}
loop={true}
pagination={false}
navigation={true} className="mySwiper">
{animeDetail.map((element, i)=>
(
<SwiperSlide key = {i}><img src={element.anime_image}/></SwiperSlide>
)
)}
</Swiper>}
How do I make a div expand smoothly when content is added?
const [render, setRender] = useState(false)
const showHide= () => {
setRender(!render)
}
return (
<div className="container">
<h1>TEST CONTAINER</h1>
{render && <Paragprah />}
<button type="button" class="btn btn-primary" onClick={showHide}>Primary</button>
</div>
);
}
CSS
.container {
margin-left: 30%;
margin-top: 10%;
width: 500px;
height: auto;
background-color: whitesmoke;
}
In the above, a component is being rendered when a button is clicked, when the new content is added to the div, it expands instantly. basically, I would like it to expand smoothly when the content is added. Here is a video as well by what I mean when it expands instantly.
Setting a fixed height wont work in my situation because the content that's being loaded is dynamic, its coming from an API and the length is different everytime. So setting a fixed height will make the content overflow sometimes. I need a way where the transition can occur smoothly and the height still be large enough to fit the content, which would probably require ```height: auto;`` to be present?
Link to Imgur video
you can use the transition css property for a smooth transition.
transition: height 2s;
Follow this link for reference.
Here I updated the code. Since the content that's being loaded has dynamic size then you have to track that content size using useRef hook and store it on a variable and export it with your component.
import { useRef, useEffect} from "react";
var ParagraphHeight;
function Paragraph() {
const ref = useRef(null);
useEffect(() => {
//when you content is loaded store its height
ParagraphHeight = ref.current.offsetHeight;
}, []);
return (
<div ref={ref}>
<p>Your content here for exemple...</p>
</div>
);
}
export { Paragraph, ParagraphHeight };
Now import your Paragraph component and put it inside a .wrapper div that has a default height of 0px (that means your Paragraph will be hidden) and when you click on the button the height of it will change to the ParagraphHeight
import { useState } from "react";
import { Paragraph, ParagraphHeight } from "./Paragraph.js";
export default function App() {
const [isopned, setisopned] = useState(false);
const [wrapperHeight, setWH] = useState(0);
const showHide = () => {
if (!isopned) setWH(ParagraphHeight);
else setWH(0);
setisopned(!isopned);
};
return (
<div className="container">
<h1>TEST CONTAINER</h1>
<div className="wrapper" style={{ height: wrapperHeight }}>
<Paragraph />
</div>
<button type="button" className="btn btn-primary" onClick={showHide}>
Primary
</button>
</div>
);
}
Finally don't forget to update your css, add overflow-y hidden and css transition to to expand your wrapper div smoothly.
.container {
margin-left: 30%;
margin-top: 10%;
width: 500px;
background-color: whitesmoke;
}
.wrapper {
display: grid; /*to prevent some problem caused by overflow hidden*/
transition: height 1s linear;
background-color: wheat;
overflow-y: hidden;
}
This is a live exemple demo
I'm using React.js + next.js + Styled Components to develop the front of an app. In my Layout file I have a Wrapper that makes the two other div's (LeftContainer and RightContainer) side by side, but none of the div's occupies 100% of the page's height. I am attaching both the Layout class and the styling below.
export default function Layout({ children }) {
return (
<>
<Wrapper>
<LeftContainer>
a
</LeftContainer>
<RightContainer>
a
</RightContainer>
</Wrapper>
</>
)
}
import styled from 'styled-components'
export const Wrapper = styled.div `
display:flex;
flex-direction:row;
height:100%;
min-height:100%;
`
export const LeftContainer = styled.div `
display:flex;
flex-direction: column;
width:100%;
//background-color: ${(props) => props.theme.colors.secondary};
background-color:black;
`
export const RightContainer = styled.div `
display:flex;
flex-direction: column;
//background-color: ${(props) => props.theme.colors.primary};
background-color:red;
width:100%;
`
The link for Github repo is: https://github.com/FranciscoJLucca/franciscolucca.github.io
If you're aiming for the element to be the height of the page, you'll want to use height: 100vh; instead. The vh stands for viewport height. The percentage will only take 100% of the height from its parent. Hope this helped.
export const Wrapper = styled.div `
display: flex;
flex-direction: row;
height: 100vh;
I have 2 boxes: Panel and Sidebar, in a flexbox, with flex-direction: row and justify-content: space-between I am able to horizontally align them side by side with a gap in the middle.
Now I'd like to fix the right Sidebar position, i.e. when scrolling down, the Sidebar should always stay on top of the screen, regardless of the location of Panel. How can I do it with CSS?
Working example here: https://codesandbox.io/s/gallant-saha-zgmnw
Code here:
App.js:
import React from "react";
import "./App.scss";
import Panel from "./Panel";
import Sidebar from "./Sidebar";
export default function App() {
return (
<div className="App">
<Panel />
<Sidebar />
</div>
);
}
App.scss:
.App {
width: 1100px;
font-family: sans-serif;
text-align: center;
display: flex;
flex-direction: row;
justify-content: space-between;
}
Panel.js:
import React from "react";
import "./Panel.scss";
const Panel = () => {
return (
<>
<div className="panel">The main panel</div>
</>
);
};
export default Panel;
Sidebar.js:
import React from "react";
import "./Sidebar.scss";
const Sidebar = () => {
return (
<>
<div className="sidebar">The sidebar</div>
</>
);
};
export default Sidebar;
I modified your siderbar css.
I used position fixed as this will make the sidebar fixed in the viewport so as you scroll it will remain static.
.sidebar {
position: fixed; /* add this */
width: 200px;
height: 200px;
text-align: center;
border: 1px black solid;
left: 906px /* add this */
}
This produces the desired effect. Tested and works. Apologies, I have updated my answer.
add this css to .sidebar
position:fixed;
right: 10px;
also, you can add:
top: -- px
if you have Navbar.
How can I place text at the bottom of a div in plain old React (not React Native)?
In html, you can place text at the bottom of a div by using
vertical-align: text-bottom;
In React Native, it looks like you place text at the bottom of a div by using
textAlignVertical: "bottom",
Is there a simple way to place text at the bottom of a div in plain old React?
The only method I got to work so far is is to use Flexbox.
import React from "react";
import "./styles.css";
export default function App() {
const style3 = {
height: "75px",
display: "flex",
justifyContent: "flex-end",
alignItems: "flex-end",
};
return (
<div className="App">
<div style={style3}>CSS Flexbox</div>
</div>
);
}
Codesandbox
Edit: This is a simplified example. What I really need is a div with items in several different spots, and text on the bottom.
Edit: In both HTML and React, vertical-align: text-bottom; does not move text to the bottom of a div. It only shifts the text down a little bit to the bottom of where the text would normally be. So in both HTML and React, it can be used to shift text down a little for a subscript. But in both HTML and React, it can't be used to shift text way down to the bottom of a div.
You could use margin:
import React from "react";
import "./styles.css";
export default function App() {
const style3 = {
height: "75px",
marginTop: 'auto'
};
return (
<div className="App">
<div style={style3}>CSS Flexbox</div>
</div>
);
}
Or align-self:
import React from "react";
import "./styles.css";
export default function App() {
const style3 = {
height: "75px",
alignSelf: 'flex-end'
};
return (
<div className="App">
<div style={style3}>CSS Flexbox</div>
</div>
);
}
I noticed you mentioned the div has lots of other information in a more complicated example. I would highly recommend trying out css grid if you haven't already. It allows you to structure the items on your screen very easily.
Here's an example using grid to create the 'holy grail layout' which is by no means the best example but it shows how easy it is to structure divs in different areas of the screen.
https://codepen.io/frazermg/pen/bXbXOR?editors=1100
.container {
display: grid;
grid-template-areas: 'header header header header'
'left content content right'
'left content content right'
'footer footer footer footer';
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(30vh, auto);
}
.header {
background-color: blue;
grid-area: header;
}
.left {
background-color: green;
grid-area: left;
}
.content {
background-color: #eee;
grid-area: content;
}
.right {
background-color: pink;
grid-area: right;
}
.footer {
background-color: orange;
grid-area: footer;
}
<div class="container">
<div class="header"></div>
<div class="left"></div>
<div class="content"></div>
<div class="right"></div>
<div class="footer"></div>
</div>
Here is an example of nested grids:
https://codepen.io/frazermg/pen/ZgEwVd
This website is very useful for all things css, especially flexbox and grid.
https://css-tricks.com/snippets/css/complete-guide-grid/
I hope this can help you!
What about simply style any span or component with text inside a div like this:
... style={{position:"absolute",bottom:"0px"}} ...