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;
Related
Lets say in my global.css file of a Next.js project I have:
.flex {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
I also have a Layout.js component and a Layout.module.css file. The component looks like this:
import styles from "../styles/Layout.module.css";
const Layout = ({ children }) => {
return (
<div>
<div className={styles.navbar}>
<div className="flex">
<h1>Structured Safety</h1>
<nav>
<ul>
<li> Home </li>
<li> Demo </li>
</ul>
</nav>
</div>
</div>
</div>
);
};
export default Layout;
and the Layout.module.css is:
/* Navbar */
.navbar {
background-color: var(--primary-color);
color: #fff;
height: 70px;
}
.navbar ul {
display: flex;
}
.navbar .flex {
justify-content: space-between;
}
Structured like this, my .navbar .flex does not overwrite the global .flex class and split the h1 from the nav. How can I accomplish overwriting my global style from this component style?
Since .flex refers to a global class you'll need to use the :global selector to target it in your CSS module.
/* Layout.module.css */
.navbar :global(.flex) {
justify-content: space-between;
}
Or using an alternate syntax.
.navbar {
:global {
.flex {
justify-content: space-between;
}
}
}
/** CSS MODULE FILE **/
.classname :global(.globalClass) { css properties }
.classname {
:global {
.globalClass { css properties }
}
}
In NextJS and React when you
import styles from "__.css" the styles becomes a variable so you have to use it in your HTML for it to take effect.
Currently you're not using any styles from your Layout.module.css, if you want to use that css you would change your html to: <div className={styles.navbar}> and such..
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
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;
`;
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.