DropDown Positioning absolute element outside of the relative parent container - css

I'm using ReactJs and Emotion, but I know the problem is related to my CSS
I have a Header structure
main (
sidebar
content
)
That's why I'm having trouble positioning an <ul> tag correctly with position absolute and this error happens:
problem gif:
I know it is related to the position: relative of my components or my page structure I already tried everything and I couldn't solve it
basically i need my <ul> dropdown to be next to my sidebar like this:
My JSX:
const Tags = () => {
const [menuItems, setMenuItems] = useState(SideBarTags);
const showHideDropItem = tag => {
setMenuItems(items =>
items.map(item => ({
...item,
Active:
item.Name === tag.Name ? (tag.Active === true ? false : true) : false
}))
);
};
return (
<SideBar.MenuList>
{menuItems.map((item, index) => (
<SideBar.ListItem>
<SideBar.ListWrap>
<a>
<item.Icon size={24} />
<span className="li-name">{item.Name}</span>
</a>
</SideBar.ListWrap>
{item.DropdownItems && (
<SideBar.ClosedStyled>
{item.DropdownItems.map(item => (
<li className="li-closed" key={item.Name}>
<FaGhost size={18} />
<a onClick={() => console.log(item.Name)}>{item.Name}</a>
</li>
))}
</SideBar.ClosedStyled>
)}
</SideBar.ListItem>
))}
</SideBar.MenuList>
);
};
export default function App() {
return (
<Global.Container>
<Header.NavBar>
<Header.LogoSide>
<img src={Logo} alt="elo Ghost" />
</Header.LogoSide>
<div style={{ width: "100%", background: "#eee" }} />
</Header.NavBar>
<Global.Main>
<SideBar.SideBodyWrap>
<SideBar.DashMenu>
<Tags />
</SideBar.DashMenu>
</SideBar.SideBodyWrap>
<Content>a</Content>
</Global.Main>
</Global.Container>
);
}
my CSS in Js:
import styled from "#emotion/styled/macro";
import { shade } from "polished";
import { css } from "#emotion/core";
// Global Containers
const Container = styled.div`
height: 100%;
`;
const Main = styled.div`
display: flex;
height: calc(100% - 55px);
position: relative;
z-index: 0;
`;
// Global Containers
export const Global = {
Container,
Main
};
// header Nav
export const NavBar = styled.div`
height: 55px;
background: #3c8dbc;
display: flex;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(0, 0, 0, 0.05);
position: relative;
z-index: 1;
`;
export const LogoSide = styled.div`
display: flex;
background: red;
justify-content: center;
background: #3c8dbc;
padding: 10px;
width: 100%;
max-width: 250px;
height: 55px;
img {
height: 35px;
transition: all 0.2s ease;
}
`;
// header Nav
export const Header = {
NavBar,
LogoSide
};
// SideBar
const SideBodyWrap = styled.nav`
overflow-y: auto;
height: 100%;
max-width: 250px;
width: 100%;
color: #009688;
background: #3c8dbc;
transition: all 0.2s ease;
::-webkit-scrollbar {
width: 5px;
}
::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
}
::-webkit-scrollbar-thumb {
background: rgba(255, 0, 0, 0.8);
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.5);
}
::-webkit-scrollbar-thumb:window-inactive {
background: rgba(255, 0, 0, 0.4);
}
`;
const MenuList = styled.ul`
font-family: "Ubuntu";
font-size: 14px;
font-weight: 300;
text-decoration: none;
color: #fff;
padding-top: 10px;
`;
export const ListItem = styled.li`
display: flex;
flex-direction: column;
justify-content: center;
cursor: pointer;
position: relative;
`;
export const ListWrap = styled.div`
padding: 12px 20px 12px 20px;
display: flex;
transition: all 0.5s cubic-bezier(0, 1, 0, 1);
justify-content: center;
align-items: center;
a {
display: flex;
align-items: center;
svg {
margin-right: 15px;
transition: all 0.5s cubic-bezier(0, 1, 0, 1);
}
}
& .icon-li {
margin-right: 10px;
}
& .down-up_svg,
.li-name {
display: none;
}
`;
export const ClosedStyled = styled.ul`
${ListItem}:hover & {
max-width: 400px !important;
max-height: 400px !important;
}
max-height: 0px !important;
overflow: hidden;
-webkit-transition: all 0.2s;
-moz-transition: all 0.2s;
-ms-transition: all 0.2s;
-o-transition: all 0.2s;
transition: all 0.2s;
list-style-type: none;
margin: 0;
padding: 0;
top: 0;
left: 70%;
font-weight: 400;
position: absolute;
padding: 0px;
z-index: 2;
background: ${shade(0.4, "#3c8dbc")};
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
& .li-closed {
white-space: nowrap;
padding: 10px 20px;
:hover > svg {
color: orange;
}
svg {
margin-right: 10px;
}
}
a {
font-family: "Ubuntu";
font-size: 14px;
font-weight: 300;
text-decoration: none;
color: #8aa4af;
}
`;
const DashMenu = styled.div`
display: flex;
flex-direction: column;
`;
export const SideBar = {
SideBodyWrap,
DashMenu,
ClosedStyled,
ListItem,
ListWrap,
MenuList
};
// SideBar
export const Content = styled.div`
height: 100%;
width: 100%;
background: #eee;
`;
example:
https://codesandbox.io/s/cranky-hamilton-oy47v?file=/src/App.js
and :
https://oy47v.csb.app/

If I'm understanding what you're wanting to achieve correctly, I was able to do it by removing overflow-y:auto from .sidebodywrap and changing left:70% to left:100% in .closedstyled

Related

How to fill a div with dots automatically

I am building a react app and I want to know what is the best way to fill a div with dots, to be more specific how to fill a div entirely with small rounded divs, but no matter the width of the screen the div is always full with small rounded divs.
The end result should look like this :
I tried to use Array.fill().map() but when the width of my screen changes the dots became unorganized.
My code :
function About() {
const service = [
{
icon: <PhoneCallbackIcon style={{ fontSize: 32 }} />,
text: "Inbound Call Center Service",
subText: "Read more"
},
{
icon: <QuestionAnswerIcon style={{ fontSize: 32 }} />,
text: "Schriftbeschreibung",
subText: "Read more"
},
{
icon: <GTranslateIcon style={{ fontSize: 32 }} />,
text: "Übersetzung",
subText: "Read more"
}
]
const dots = 266
return (
<Container>
<OurJob>
<Title>Was machen wir?</Title>
<Line />
<p>Wir sind Experten in diesen Bereichen</p>
</OurJob>
<OurServices>
{service.map((item, index) => (
<Service key={index} >
{item.icon}
<div>
{item.text}
</div>
<p>
{item.subText}
</p>
</Service>
))}
</OurServices>
<Dots >
{Array(dots).fill().map((_, i) => (
<Dot />
))}
</Dots>
</Container>
)
}
My styled components :
const Container = styled.div`
display: flex;
width: 100%;
border-radius: 16px;
position: relative;
margin: 5% 0;
box-shadow: 9px 11px 17px -6px rgba(0,0,0,0.3);
-webkit-box-shadow: 9px 11px 17px -6px rgba(0,0,0,0.3);
-moz-box-shadow: 9px 11px 17px -6px rgba(0,0,0,0.3);
`
const Dots = styled.div`
position: absolute;
width: 33%;
display: flex;
flex-wrap: wrap;
left: -4%;
bottom: -25%;
`
const Dot = styled.div`
width: 4px;
content: "";
height: 4px;
margin: 5px 5.5px;
border-radius: 50%;
/* background: rgba(217, 217, 217, 0.5); */
background: black;
`
const OurJob = styled.div`
width: 25%;
padding: 40px;
background: rgba(122, 223, 210, 1);
overflow: hidden;
border-radius: 16px 0 0 16px;
p {
font-size: 20px;
font-weight: 400;
color: white;
}
`
const Line = styled.div`
height: 8px;
background: white;
width: 60%;
margin: 10px 0;
`
const Title = styled.div`
font-size: 50px;
font-weight: 600;
color: white;
`
const OurServices = styled.div`
display: flex;
width: 70%;
`
const Service = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 40px;
width: 25%;
text-align: center;
div {
font-size: 22px;
font-weight: 600;
height: 20%;
}
p {
color: rgba(92, 92, 92, 1);
font-size: 20px;
}
`
This can be done by setting a div with a background image and use a URL that's an encoded svg as follows:
.dots {
width: 100%;
height: 50vh;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='20' width='20'%3E%3Ccircle cx='10' cy='10' r='5' fill='%23e0e0e0' /%3E%3C/svg%3E ");
}
<div class='dots'>
</div>
You can also create it without svg image on the body or your container.
You can play with the background-size to add/remove space between the dots.
body {
background-image: radial-gradient(rgba(217, 217, 217, 0.5) 4px, transparent 0);
background-size: 30px 30px;
}

Cannot hide images under fixed div

Images are visible from underneath fixed div and I cannot hide them. Tried with z-index but didn't rly work. It looks like only image is visible from underneath since div in which these images are mapped cannot be seen. What is causing the problem?
styles of component with fixed div (MenuPopUp)
export const MenuWrapper = styled.div``;
export const IconWrapper = styled.div<{
isActive: boolean;
isDarkMode: boolean;
}>`
height: 40px;
width: 40px;
display: flex;
align-items: center;
justify-content: center;
background-color: ${(props) =>
guessIconBgColor(props.isActive, props.isDarkMode)};
border-radius: 50%;
cursor: pointer;
&:hover {
background-color: ${pallete.DarkerGray};
}
svg {
height: 20px;
color: ${(props) => guessIconColor(props.isActive, props.isDarkMode)};
}
`;
export const MenuPopUp = styled.div`
position: fixed;
width: 675px;
height: 672px;
right: 16px;
background-color: ${pallete.LightGray};
border-radius: 0 0 4px;
-webkit-box-shadow: 6px 6px 15px -7px rgba(66, 68, 90, 1);
-moz-box-shadow: 6px 6px 15px -7px rgba(66, 68, 90, 1);
box-shadow: 6px 6px 15px -7px rgba(66, 68, 90, 1);
`;
styles of images
export const UserStoryWrapper = styled.div`
position: relative;
display: flex;
align-items: center;
justify-content: center;
flex: 1;
height: 100%;
border-radius: 8px;
overflow: hidden;
`;
export const Image = styled.img<{ isOverlay: boolean }>`
height: 100%;
width: 100%;
scale: ${(props) => (props.isOverlay ? "1.05" : "1")};
transition: 0.3s ease-in-out;
`;
export const Overlay = styled.div<{ isOverlay: boolean }>`
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0);
opacity: ${(props) => (props.isOverlay ? "0.3" : "0")};
cursor: pointer;
`;
styles of images container
export const UserStoriesWrapper = styled.div`
display: flex;
flex-direction: row;
align-items: center;
gap: 8px;
height: 200px;
`;

Search bar won't stay at top with CSS position: sticky property

I am trying to make a search bar stay at the top of a div with position: sticky but the property doesnt seem to work. Googling it, I see that overflow: hidden and overflow: hidden on a parent element can make it unresponsive if there is no height specified but I have a height specified so I don't think that's it. Here is the relevant CSS:
.container {
background-color: white;
box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
border-radius: 1rem;
height: 85vh;
width: 60vw;
overflow-y: scroll;
overflow-x: hidden;
margin: auto;
}
.search-bar {
position: sticky;
top: 0;
margin: 1rem 1rem;
padding: 0.5rem;
font-size: 20px;
width: 100%;
display: block;
outline: 0;
border-width: 0 0 2px;
}
Note that .search-bar is a child element of .container. If needed, here is the JSX file (it's a react app):
import React, { useState, useEffect } from 'react';
import { average } from './utils/util.js';
import Card from './components/Card/Card';
import './App.css';
function App() {
const [loading, setLoading] = useState(true);
const [query, setQuery] = useState({ name: '', tag: '' });
const [users, setUsers] = useState([]);
const [filteredUsers, setFilteredUsers] = useState([]);
return (
<div className='container'>
<input
className='search-bar'
placeholder='Search by name'
onChange={(e) => {
setQuery({ ...query, name: e.target.value });
}}
/>
<input
className='search-bar'
placeholder='Search by tag'
onChange={(e) => {
setQuery({ ...query, tag: e.target.value });
}}
/>
{filteredUsers.map((user) => (
<Card
id={user.id}
pic={user.pic}
name={`${user.firstName} ${user.lastName}`}
email={user.email}
company={user.company}
skill={user.skill}
average={average(user.grades)}
grades={user.grades}
tags={user.tags}
onTagChange={tagChange}
/>
))}
</div>
);
}
export default App;
I tried to reproduce your issue here,
https://codesandbox.io/s/winter-breeze-5spod8?file=/src/styles.css
but it seems to work fine with your code. The only thing I changed was to add two .search-bar classes and height into it, because you have two input elements which you want sticky and they start to overlap on each other when we start scrolling.
.container {
background-color: white;
box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
border-radius: 1rem;
height: 85vh;
width: 60vw;
overflow-y: scroll;
overflow-x: hidden;
margin: auto;
}
.search-bar1 {
position: sticky;
top: 0;
margin: 1rem 1rem;
padding: 0.5rem;
font-size: 20px;
width: 100%;
height: 3%;
display: block;
outline: 0;
border-width: 0 0 2px;
}
.search-bar2 {
position: sticky;
top: 5.8%;
margin: 1rem 1rem;
padding: 0.5rem;
font-size: 20px;
width: 100%;
height: 3%;
display: block;
outline: 0;
border-width: 0 0 2px;
}

How to make close effect after clicking on close in Styled-components?

I'm trying to make an in and out animation for my comment -
import {
Popup,
Overlay,
NavBarPopupHeader,
NavBarPopupContainer,
NavBarPopupImg,
NavBarPopupClose,
NavBarPopupContent,
NavBarPopupTitle,
NavBarPopupInfo,
NavBarPopupContentImg,
NavBarPopupFooter,
NavBarPopupSignOut,
} from "./styled.js";
function NavBarPopup(props) {
const { isPopupOpen } = props;
return (
<Overlay>
<Popup active={false}>
<NavBarPopupHeader>
<NavBarPopupClose
src="./popup_close.svg"
alt="close"
onClick={() => isPopupOpen(false)}
active={true}
/>
<NavBarPopupContainer>
<NavBarPopupImg />
</NavBarPopupContainer>
</NavBarPopupHeader>
<NavBarPopupContent>
<NavBarPopupTitle>You are logged as</NavBarPopupTitle>
<NavBarPopupInfo>'UserName'</NavBarPopupInfo>
<NavBarPopupInfo>'Email'</NavBarPopupInfo>
<NavBarPopupContentImg src="./popup_img.png" />
</NavBarPopupContent>
<NavBarPopupFooter>
<NavBarPopupSignOut>Sign Out...</NavBarPopupSignOut>
</NavBarPopupFooter>
</Popup>
</Overlay>
);
}
export default NavBarPopup;
I am using styled-components :
import styled, { keyframes, css } from "styled-components";
import { fadeIn, bounceInRight, bounceInLeft } from 'react-animations';
const fader = keyframes`${fadeIn}`;
const bounceIn = keyframes`${bounceInRight}`;
const bounceOut = keyframes`${bounceInLeft}`;
const Popup = styled.div`
position: fixed;
top: 0;
right: 0;
height: 100vh;
width: 400px;
background-color: #ffffff;
transition: ${(active) =>
active
? css`
${bounceIn} 0.5s linear
`
: css`${bounceOut} 0.5s`};
`;
const Overlay = styled.div`
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: rgba(0, 0, 0, 0.8);
animation: 0.2s ${fader};
`;
const NavBarPopupHeader = styled.div`
width: 100%;
height: 15%;
background-color: #000000;
`;
const NavBarPopupContainer = styled.p`
text-align: center;
margin: 0;
padding: 30px 0 0 0;
`;
const NavBarPopupImg = styled.img`
width: 80px;
height: 80px;
border-radius: 50px;
border: none;
background-color: white;
color: black;
font-size: 25px;
`;
const NavBarPopupClose = styled.img`
position: absolute;
top: 5px;
left: 5px;
cursor: pointer;
`;
const NavBarPopupContent = styled.div`
height: 75%;
`;
const NavBarPopupTitle = styled.h3`
margin:0;
padding: 10px 0 10px 0;
text-align: center;
font-size: 30px;
`
const NavBarPopupInfo = styled.h4`
width: 80%;
margin: 10px auto;
padding:5px;
text-align: center;
font-size: 25px;
background-color: black;
color:white;
border-radius: 15px;
`
const NavBarPopupContentImg = styled.img`
width:100%;
margin-top:90px;
`
const NavBarPopupFooter = styled.div`
width: 100%;
height: 10%;
background-color: #000000;
`;
const NavBarPopupSignOut = styled.p`
width:200px;
text-align: center;
margin: 0 auto;
padding: 15px 0 0 0;
font-weight: 700;
font-size: 32px;
color: white;
text-decoration: underline;
cursor: pointer;
`;
export {
Popup,
Overlay,
NavBarPopupHeader,
NavBarPopupContainer,
NavBarPopupImg,
NavBarPopupClose,
NavBarPopupContent,
NavBarPopupTitle,
NavBarPopupInfo,
NavBarPopupContentImg,
NavBarPopupFooter,
NavBarPopupSignOut
};
I want my popup to be animated with $bounceIn when it appears, and disappear with $bounceOut when it closes. I tried to do it by passing an attribute to styled-components but now it only works when my Popup appears. Perhaps I chose the wrong approach, in which case please guide me in the right direction.

Parent with height: self doesn't have children's height

Hello I have a parent with positon absolut and height: self that is not with the height of children like this:
css:
const UserProfile = styled.div`
display: flex;
justify-content: center;
align-items: center;
padding: 0 0.5rem;
cursor: pointer;
position: relative;
& .user_text {
cursor: pointer;
display: flex !important;
flex-direction: column;
padding-right: 0.75rem !important;
span:first-of-type {
font-size: 1rem;
color: #b5b5c3 !important;
font-weight: 500 !important;
text-align: right !important;
}
span:last-of-type {
font-size: 1rem;
color: #464e5f !important;
font-weight: 600 !important;
text-align: right !important;
}
}
& .user_avatar {
border-radius: 50%;
flex-shrink: 0;
position: relative;
transition: border-color 0.2s;
width: 45px;
z-index: 1;
img {
min-height: 100%;
object-fit: cover;
-o-object-fit: cover;
width: 100%;
}
}
`;
const UserCanvas = styled.div`
position: absolute;
min-width: 10rem;
display: ${props => (props.isOpen ? "block" : "none")};
border: 1px solid rgba(0, 0, 0, 0.15);
border-color: rgba(120, 130, 140, 0.13);
box-shadow: 0 3px 12px rgba(0, 0, 0, 0.05);
top: 100%;
bottom: 0;
font-size: 1rem;
color: #212529;
background-color: #fff;
background-clip: padding-box;
border-radius: 0.25rem;
& .test {
min-width: 10rem;
height: 200px;
}
`;
jsx:
<UserProfile onClick={() => setOpen(!isOpen)}>
<div className="user_text">
<span>SpiriT</span>
<span>Web Developer</span>
</div>
<div className="user_avatar">
<img src={LogoImage} />
</div>
<UserCanvas isOpen={isOpen}>
<div className="test">a</div>
</UserCanvas>
</UserProfile>
example:
https://codesandbox.io/s/youthful-hooks-ceo85?file=/src/App.js:743-2099
basically i need the div with position absolute and height auto to follow the height of yours children
Change the display to table for the parent component and table-row t like this:
const UserCanvas = styled.div`
// ... other properties
display: ${props => (props.isOpen ? "table" : "none")};
& .test {
min-width: 10rem;
height: auto;
display: table-row;
}
`;
Alternately, you can add height: max-content; to the Parent Component.

Resources