Flexbox spacing items in nav bar - html

I'm trying to space items within a nav bar where I have tags and search bar. I tried space-between, but not show how to properly position the search bar to get it to be slightly larger. Is this some combo of flex-end?
Attempt
Mock-Up
The box on the right should be slightly larger.
Code
Container
const TagsContainer = styled.div`
display: flex;
width: 100%;
margin-top: 15px;
`
export default function Tags() {
return (
<TagsContainer>
<Tag>Algorithms</Tag>
<Tag>Videos</Tag>
<Tag>Books</Tag>
<Tag>Tutorials</Tag>
<Tag>Health</Tag>
<Tag>Finance</Tag>
<Tag>Rants</Tag>
<Tag>Stream</Tag>
<Tag>Music</Tag>
<Search />
</TagsContainer>
)
}
Tag
const TagContainer = styled.div`
height: 100%;
max-height: 40px;
opacity: .8;
text-align: center;
`
const TagStyle = styled.span`
font-family: 'Lora';
min-width: 80px;
color: white;
padding: 10px;
border: 1px solid white;
font-size: 15px;
`
export default function Tag({ children }) {
return (
<>
<TagContainer>
<TagStyle>
{ children }
</TagStyle>
</TagContainer>
</>
)
}
Search
const SearchContainer = styled.div`
color: white;
border: 1px solid black;
flex-grow: 2;
min-height: 40px;
height: 100%;
`
export default function Search() {
return (
<>
<SearchContainer>
This is a search box
</SearchContainer>
</>
)
}

Add flex-grow: 1; to TagContainer to allow all flex items to grow

Related

Why does the view of the website gets out of the HTML size?

I have a navbar that contains the button that triggers the movement of the main container to the right and brings the nav elements to the right:
The cards in the middle have an animation that modifies their flex-grow when hovering and shows some text:
But when you hit the nav toggle button when one of these sections is being hovered this happens:
What I'm not understanding is that this view is out of the HTML element size and in theory it shouldn't look like this.
This is the code for the card, made with react & styled-components:
import styled from "styled-components"
const CardDiv = styled.div`
display: flex;
flex-direction: column;
position: relative;
justify-content: space-between;
background-color: var(--Scania-Grey-900-transparent);
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
transition: flex-grow .5s;
&:hover {
flex-grow: 2;
}
&:hover .card_description_text {
opacity: 1;
line-height: 1.5em;
}
`
const Title = styled.h1`
font-family: var(--Scania-Font);
text-transform: uppercase;
color: var(--Scania-White);
`
const ImageBackground = styled.div`
background-image: url(${props => props.background_image});
background-repeat: no-repeat;
background-size: cover;
background-position: ${props => props.bg_position};
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
`
const Description = styled.div`
display: flex;
flex-direction: column;
color: var(--Scania-White);
opacity: 0;
transition: opacity .2s, line-height .5s;
line-height: .5px;
`
const Text = styled.p`
font-family: var(--Scania-Font-2);
margin: .8em;
font-size: 1.1em;
`
const Padding = styled.div`
margin: .8em;
`
const Button = styled.a`
padding: .4em .8em;
border: 2px solid var(--Scania-White);
margin: .8em;
text-align: center;
font-family: var(--Scania-Font);
font-size: 1.1em;
`
const Card = ({ background_image, title, bg_position, text, button_text }) => {
return (
<CardDiv>
<ImageBackground background_image={background_image} bg_position={bg_position} role="background_image_card" />
<Padding>
<Title>{title}</Title>
</Padding>
<Description className="card_description_text">
<Text>{text}</Text>
<Button>{button_text}</Button>
</Description>
</CardDiv>
)
}
export default Card
I'm sorry if this question is poor or if I don't know how to ask the question, but I would like to receive some help. Thank you :=)
EDIT:
This is the code of my main component Home():
export default function Home() {
/* This state is for the status of the navbar */
const [statusNavbar, setActiveNavbar] = useState(false)
const changeStatus = () => {
setActiveNavbar(!statusNavbar)
}
return (
<Main>
<Navbar setNavbarStatus={changeStatus} />
<Container statusNavbar={statusNavbar} />
</Main>
)
}
this Container.jsx: is the component that goes after the navbar:
const Container = ({ statusNavbar }) => {
return (
<DivContainer>
<NavbarElements navbarStatus={statusNavbar} />
<Content navbarStatus={statusNavbar} />
</DivContainer>
)
}
export default Container
NavbarElements component is the part which is hidden by default, and when the burger is clicked, it comes to the right. And Content component is where the content is included the cards.
NavbarElements.jsx code:
const Div = styled.div`
position: absolute;
top: 0;
left: 0;
background-color: var(--Scania-Grey-400);
min-height: 100%;
width: ${sizesConfig.left_side_size}%;
padding-right: ${sizesConfig.padding_spacing}%;
transform: ${props => props.navbarStatus ? 'translateX(0%)' : 'translateX(-100%)'};
transition: transform .5s ease;
`
const NavbarElements = ({ navbarStatus }) => {
return (
<Div navbarStatus={navbarStatus} role="Navbar-content">NavbarElements</Div>
)
}
export default NavbarElements
Content.jsx code:
const Div = styled.div`
transform: ${props => props.navbarStatus ? `translateX(${sizesConfig.left_side_size}%)` : 'translateX(0%)'};
transition: transform .5s ease;
flex: 1 0;
display: flex;
`
const Content = ({ navbarStatus }) => {
return (
<Div navbarStatus={navbarStatus}>
<CardsGrid />
</Div>
)
}
export default Content
In case you were wondering, this is the sizesConfig object which is being used to change the sizes easily
Navbar.config.js code:
const left_side_size = 75
const padding_spacing = 100 -left_side_size
export const sizesConfig = {
left_side_size,
padding_spacing,
}
So I managed to find a solution, from this post:
How can I "disable" zoom on a mobile web page?
The answer from #kgutteridge it's incorrect in this case since it has a problem:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
The meta tag above solves my problem about the viewport, but removes the capability of the user to zoom in/out which I read is a bad practice
#SW4 provides a better answer for problems like mine:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
The meta tag above:
Renders the page at the width of the device, don't scale:
Which was exactly what I was looking for.

TextArea dont auto-resize correct when starting on one row

I having some trouble to get a textarea to auto expand from one row.
It works when I have 3 or more rows and one row, but the two first looks weird.
Can't find a good way of knowing when the text is clipped like that. Because the lenght of the input will be dynamic.
I have seen solutions that kind of work here on Stackoverflow, but I must have the total height of the input to start at 40px; And the solutions I have seen cant handle that case.
(Dont mind the black-border for the textarea, for some reason codeSandBox shows it but not for me.)
I have a codeSandbox that shows the issue:
https://codesandbox.io/s/affectionate-yalow-fnqnep?file=/src/App.js:241-296
Anyone had a similliar issue or could point me in the right direction?
Edit:
Working React component:
import React, { useState, useEffect } from "react";
import styled from "styled-components";
const InputWrapper = styled.div`
display: inline-flex;
justify-content: flex-start;
align-items: center;
width: 100%;
padding: 8px 16px;
border-radius: 6px;
background-color: white;
border: 1px solid black;
`;
const StyledTextArea = styled.textarea`
width: 100%;
max-height: 300px;
font-size: 16px;
background-color: white;
line-height: 18px;
resize: none;
transition: all 300ms;
border: none;
overflow: hidden;
`;
const TextArea = ({ value, placeholder, handleEvent }) => {
const [textAreaRef, setTextAreaRef] = useState(React.createRef());
const updateHeight = () => {
const updatedTextArea = { ...textAreaRef };
updatedTextArea.current.style.height = "";
updatedTextArea.current.style.height = `${updatedTextArea.current.scrollHeight}px`;
setTextAreaRef(updatedTextArea);
};
useEffect(() => updateHeight(), [value]);
return (
<InputWrapper>
<StyledTextArea
ref={textAreaRef}
value={value}
rows={1}
placeholder={placeholder}
onChange={handleEvent}
/>
</InputWrapper>
);
};
export default TextArea;

Top left space of grid not being used when fetching data from a foreach

Im fetching some data from Firestone consisting of an image and text that I want to display in a grid. Im using a foreach so the website changes the data in firestore for ease.
But when I style this into a grid it leave a space in the top left as if it put content there (but not seen). Im not sure why it misses this space (I have attached a image of what happens)
I would like my grid to start from the left side and not the right as it is now.
const i = query(collection(db, "teams"));
const unsubscribe = onSnapshot(i, (querySnapshot) => {
const teams = document.querySelector('.teams');
querySnapshot.forEach((doc) => {
const docData = doc.data();
const article = teams.appendChild(document.createElement('article'));
article.innerHTML = `
<h1 class="team-names"></h1>
<div class="team-line"></div>
<img class="team-image">
`;
article.children[0].textContent = docData.ageGroup;
article.children[2].src = docData.teamImage;
console.log("Current data: ", docData);
});
});
.teams {
display: grid;
place-items: left;
max-width: 950px;
margin: 0 auto 30px;
padding: 10px;
}
.team-names {
width: 180px;
color: #000000;
border-radius: 8px;
text-align: left;
}
.team-line {
background-color: #c00000;
height: 5px;
width: 40px;
padding-top: 5px;
}
.team-image {
width: 100%;
height: auto;
object-fit: cover;
padding: 20px 0px 30px 0px;
}
<section class="teams">
<article></article>
</section>
https://i.stack.imgur.com/uE2N8.png
Try to remove the empty article in your section element :
<section class="teams">
<article></article>
</section>

Why is Text After Image, Not Inline (React) + Why Won't Hover Line Appear?

Currently trying (and failing) to learn React for a project, and not understanding why the header links appear after the image, if they're in the same wrapper. I made different components for different parts of the navbar, and made a different file for the Logo and NavLinks (each in its own section). Here's the code.
App.js
// Importing NavBar
import NavBar from './components/navbar/NavBar';
// Actual App function, has our code
function App() {
return (
<div className="App">
{/* Navbar Declaration, with statement of what links to add */}
<NavBar />
</div>
);
}
export default App;
NavBar.js
// Importing react
import React from "react";
// Importing styled to be able to style the page
import styled from "styled-components";
// Importing the logo
import Logo from "../logo/Logo";
// Importing the links
import NavLinks from "./NavLinks.js";
// ---------------------------- Stylizing the navbar using styled-components
// Main Wrapper for Navbar
const Wrapper = styled.div`
width: 100%;
height: 10rem;
align-items: center;
padding: 0 1.5 rem;
transition: background-color .5s ease;
z-index: 9999;
border-bottom: 2px solid rgba(255,255,255,.05);
margin-left: 50px;
margin-right: 50px;
`;
// NavBar is separated into left, center and right
// Left side of Navbar
const LeftSide = styled.div`
display: flex;
`;
// Center of Navbar
// Flex is a way to define how much each portion is gonna take of the size given to it
const Center = styled.div`
display: flex;
`;
// Right side of Navbar
const RightSide = styled.div`
display: flex;
`;
// Declaration of navbar links
const navbarLinks = [
"Home Page",
"Illustrator Gallery",
"Art Gallery",
"Challenges"
];
/*const navbarLinks = [
{ title: `Home Page`, path: `/` },
{ title: `Illustrator Gallery`, path: `/illustrator-gallery` },
{ title: `Art Gallery`, path: `/art-gallery` },
{ title: `Challenges`, path: `/challenges` }
];*/
// ---------------------------- Creating the NavBar function/component
function NavBar(props) {
// Setting the return value, or the component
return(
<Wrapper>
{/* For the left side, we want to import the Logo component */}
<LeftSide>
<Logo />
</LeftSide>
<Center>
{/* For the middle, we want to add the different links */}
<NavLinks links={navbarLinks} />
</Center>
<RightSide></RightSide>
</Wrapper>
);
}
export default NavBar;
Logo.js
// Importing react
import React from 'react';
// Importing styled components
import styled from "styled-components";
// Importing the image
import USLogo from "../../assets/images/bunny.png"
// Styling the wrapper for the logo
const LogoWrapper = styled.div`
display: flex;
align-items: center;
`;
// Styling the actual logo, as well as its container
const LogoImg = styled.div`
width: 50px;
height: 50px;
img {
width: 100%;
height: 100%;
}
`;
// Styling the information next to the logo
const LogoText = styled.h2`
text-transform: uppercase;
font-size: 3rem;
font-weight: bold;
margin-left: 4px;
padding-top: 8px;
color: black;
`;
// Creating logo
function Logo(props) {
return(
// First we make the wrapper
<LogoWrapper>
{/* Inside the wrapper we'll have the image, then the text */}
<LogoImg><img src={USLogo} alt="US. logo"/></LogoImg>
<LogoText>US.</LogoText>
</LogoWrapper>
);
}
export default Logo;
NavLinks.js
// Importing react
import React from 'react';
// Importing styling
import styled from 'styled-components';
// Styling the container for the links
const LinksContainer = styled.div`
display: flex;
align-items: center;
`;
// Styling the ul components, or the menu
const LinksMenu = styled.ul`
display: inline-block;
text-transform: uppercase;
letter-spacing: 3px;
`;
// Styling each li
const LinksItem = styled.li`
display: inline-block;
vertical-align: top;
align-items: center;
justify-content: space-between;
margin-top: 15px;
padding: 0 1.1rem;
`;
// Styling each link
const Link = styled.a`
text-decoration: none;
color: black;
font-size: 1.6rem;
margin: 0 2rem;
position: relative;
&:hover{
color: rgb(24, 23, 23);
}
&::after {
content: '';
width: 100%;
height: 2px;
background-color: black;
left: 0;
bottom: -3px;
transform: scaleX(0);
transform-origin: left;
transition transform .5s ease;
}
&:hover::after{
transform: scaleX(1);
}
`;
// Creating the navigation links component
function NavLinks(props) {
return(
// First we do the container
<LinksContainer>
{/* Inside the container, we have the menu of links, then the li, and finally links */}
<LinksMenu>
{/* Each link Menu has a bunch of items, with each item having a link */}
{
props.links.map(
(label) => {
return(
<LinksItem><Link>{label}</Link></LinksItem>
)
}
)
}
</LinksMenu>
</LinksContainer>
);
}
export default NavLinks;
The result shows as follows:
Additionally, if I hover over the text, it doesn't change anything. In fact, it doesn't even add the little blue color indicating it's a link anymore. I'm not sure if this is a syntactical problem, since the same code works fine when using css.
I've checked other answers on here suggesting float: left and the like for the wrapper, but for some reason they don't work. Either I'm putting them in the wrong object, or they should be somewhere else.
Any help is appreciated!

Angular. Drag & drop in flex list

I need drag & drop divs in the list. But div move strangely. Objects are not moved to the places that I need.
TS:
timePeriods = [
'1', '2', '3', '4', '5', '6', '7'
];
drop(event: CdkDragDrop<string[]>) {
moveItemInArray(this.timePeriods, event.previousIndex, event.currentIndex);
}
HTML:
<div cdkDropList cdkDropListOrientation="horizontal" class="list" (cdkDropListDropped)="drop($event)">
<div class="box" *ngFor="let timePeriod of timePeriods" cdkDrag>{{timePeriod}}</div>
CSS:
.box {
width: 33%;
border: solid 1px #ccc;
margin: 3em;
}
.list {
width: 100%;
border: solid 1px #ccc;
height: 90%;
display: flex;
flex-direction: row;
background: white;
border-radius: 4px;
overflow: hidden;
justify-content: space-around;
flex-wrap: wrap;
}
This is a duplicate to Angular CDK drag and drop issue inside CSS flexbox.
As answered there I suggest creating an items table matrix representing your flex list. I have posted a detailed explanation here: https://taitruong.github.io/software-developer.org/post/2019/10/26/Angular-drag'n'drop-mixed-orientation-in-flex-row-wrap/
I have implemented a solution on StackBlitz for your problem here: https://stackblitz.com/edit/angular-drag-and-drop-in-flex-list
Template:
<div #rowLayout cdkDropListGroup>
<!-- based on row layout's width and item box width, columns per row can be calculated and a items table matrix is initialized-->
<div
*ngFor="let itemsRow of getItemsTable(rowLayout)"
cdkDropList
class="list"
cdkDropListOrientation="horizontal"
[cdkDropListData]="itemsRow"
(cdkDropListDropped)="reorderDroppedItem($event)"
>
<!-- drop reorders items and recalculates table matrix-->
<div class="box" *ngFor="let item of itemsRow" cdkDrag>
<div class="drag-placeholder" *cdkDragPlaceholder></div>
{{ item }}
</div>
</div>
</div>
CSS:
.box {
width: 33%;
border: solid 1px #ccc;
margin: 1em;
}
.list {
width: 100%;
border: solid 1px #ccc;
height: 90%;
display: flex;
flex-direction: row;
background: white;
border-radius: 4px;
overflow: hidden;
justify-content: space-around;
flex-wrap: wrap;
}
.drag-placeholder {
background: #ccc;
width: 3em;
border: dotted 3px #999;
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
Component:
export class AppComponent {
timePeriods = ["1", "2", "3", "4", "5", "6", "7"];
itemsTable: Array<string[]>;
getItemsTable(rowLayout: Element): string[][] {
if (this.itemsTable) {
return this.itemsTable;
}
// calculate column size per row
const { width } = rowLayout.getBoundingClientRect();
const boxWidth = Math.round(width * .33); // 33% as defined in css
const columnSize = Math.round(width / boxWidth);
// calculate row size: items length / column size
// add 0.5: round up so that last element is shown in next row
const rowSize = Math.round(this.timePeriods.length / columnSize + .5);
// create table rows
const copy = [...this.timePeriods];
this.itemsTable = Array(rowSize)
.fill("")
.map(
_ =>
Array(columnSize) // always fills to end of column size, therefore...
.fill("")
.map(_ => copy.shift())
.filter(item => !!item) // ... we need to remove empty items
);
return this.itemsTable;
}
reorderDroppedItem(event: CdkDragDrop<number[]>) {
// clone table, since it needs to be re-initialized after dropping
let copyTableRows = this.itemsTable.map(_ => _.map(_ => _));
// drop item
if (event.previousContainer === event.container) {
moveItemInArray(
event.container.data,
event.previousIndex,
event.currentIndex
);
} else {
transferArrayItem(
event.previousContainer.data,
event.container.data,
event.previousIndex,
event.currentIndex
);
}
// update items after drop
this.timePeriods = this.itemsTable.reduce((previous, current) =>
previous.concat(current)
);
// re-initialize table
let index = 0;
this.itemsTable = copyTableRows.map(row =>
row.map(_ => this.timePeriods[index++])
);
}
}