I have prepared a multi-element slider that has no functionality yet. Its task is to move the elements by the number of visible elements on the screen. Unfortunately, I have to use js for this, react is out of the question.
I should use also redux with UseState from another file. Problem is I don't know how it should works in JS.
JS
import React from 'react';
import styles from './Brands.module.scss';
import Button from '../../common/Button/Button';
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome';
import { faAngleLeft, faAngleRight } from '#fortawesome/free-solid-svg-icons';
const Brands = () => {
return (
<div className={styles.root}>
<div className='container'>
<div className='row'>
<div className={styles.thumbnailNavigationWrapper}>
<Button className={styles.arrow} variant='small'>
<FontAwesomeIcon icon={faAngleLeft}>Left</FontAwesomeIcon>
</Button>
<div className={styles.thumbnailMenu}>
<ul>
<li>
<a href='#' className={styles.activeThumbnail}>
<img src='/images/brands/brands-1.jpg' alt='brand'></img>
</a>
</li>
<li>
<a href='#'>
<img src='/images/brands/brands-2.jpg' alt='brands'></img>
</a>
</li>
<li>
<a href='#'>
<img src='/images/brands/brands-3.jpg' alt='brands'></img>
</a>
</li>
<li>
<a href='#'>
<img src='/images/brands/brands-4.jpg' alt='brands'></img>
</a>
</li>
<li>
<a href='#'>
<img src='/images/brands/brands-5.jpg' alt='brands'></img>
</a>
</li>
<li>
<a href='#'>
<img src='/images/brands/brands-6.jpg' alt='brands'></img>
</a>
</li>
</ul>
</div>
<Button className={styles.arrow} variant='small'>
<FontAwesomeIcon icon={faAngleRight}>Right</FontAwesomeIcon>
</Button>
</div>
</div>
</div>
</div>
);
};
export default Brands;
SCSS
#import "../../../styles/settings.scss";
.root {
padding: 2rem 0;
display: flex;
justify-content: center;
.thumbnailNavigationWrapper {
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 90px;
border: 1px solid $new-furniture-border-color;
.arrow {
font-size: 20px;
height: 70px;
width: 30px;
display: flex;
align-items: center;
}
ul {
position: relative;
display: flex;
list-style: none;
margin: 0;
padding: 0;
li {
width: 150px;
height: 70px;
margin: 10px;
a {
opacity: 0.5;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
}
}
}
}
Since all your list elements have the same width of 150px, you could create a state/variable (e. g. activeIndex) with the active list element index. When sliding, change the index (+/- 1) and give the slider a dynamic style attribute with a translateX(calc(activeIndex * 150px)) or something like this.
Does this help?
Related
As the title states, I'm making a tabbed section to switch content upon click which works fine, how can I make it so upon clicking a new tab it has a smooth transition to the content as well as prevent jumping to the top of the page every time I click a tab?
I've tried adding the function which prevents it for links but this isn't a link so that doesn't seem to be working.
HTML
<section class="featured-books">
<div class="featured-books-title"><h2>Featured Books</h2></div>
<ul class="tabs">
<li data-tab-target="#featured" class="active tab">Featured</li>
<li data-tab-target="#on-sale" class="tab">On Sale</li>
<li data-tab-target="#most-viewed" class="tab">Most Viewed</li>
</ul>
<div id="featured" data-tab-content class="active">
<div class="featured-tab">
<img src="./images/12-rules.jpg">
<img src="./images/7-habits.jpg">
<img src="./images/art-of-war.jpg">
<img src="./images/boundaries.jpg">
<img src="./images/unlimited-memory.jpg">
<img src="./images/meaning-of-marriage.jpg">
<img src="./images/meditations.jpg">
<img src="./images/peaceful-parents.jpg">
<img src="./images/plant-paradox.jpg">
<img src="./images/spirit-filled-life.jpg">
<img src="./images/javascript-definitive-guide.jpg">
<img src="./images/atomic-habits.jpg">
</div>
</div>
<div id="on-sale" data-tab-content>
</div>
<div id="most-viewed" data-tab-content>
</div>
</section>
CSS
.featured-books h1 {
display: flex;
justify-content: center;
}
[data-tab-content] {
display: none;
}
.active[data-tab-content] {
display: block;
}
.tabs {
display: flex;
justify-content: center;
list-style-type: none;
margin: 0;
padding-bottom: 60px;
padding-top: 16px;
}
.tab {
border-radius: 20px;
cursor: pointer;
padding: 10px;
}
.tab.active {
background-color: #CCC;
}
.tab:hover {
background-color: #aaa;
}
/**------FEATURED TAB CONTENT------*/
.featured-tab {
position: absolute;
justify-content: center;
align-items: center;
margin-top: 10px;
width: 100vw;
display: grid;
grid-template-columns: repeat(auto-fill,minmax(300px,300px));
column-gap: 3px;
row-gap: 40px;
}
.featured-tab img {
width: 180px;
height: auto;
object-fit: cover;
object-position: center;
}
JavaScript
const tabContents = document.querySelectorAll('[data-tab-content]')
tabs.forEach(tab => {
tab.addEventListener('click', () => {
const target = document.querySelector(tab.dataset.tabTarget)
tabContents.forEach(tabContent => {
tabContent.classList.remove('active')
})
tabs.forEach(tab => {
tab.classList.remove('active')
})
tab.classList.add('active')
target.classList.add('active')
})
})
Here is a simple example using a opacity transition but you can use height, width or transform if you would like. I use aria-attributes to keep track of things like which article is open and if the information in the article should be picked up by screen readers. The two most important CSS classes are show and hide. These control the opacity and when the transition takes place. Show has a slight delay so it waits for the one being hidden to get out of the way. As far as the JavaScript.
Select all the buttons that have popups.
Create a event listener to handle the click.
Select the controlled article and all the articles.
Check if the controlled article is currently hidden.
If it is hide all the artiles.
Change all the buttons aria-expanded attributes to false.
Set the aria-expanded attribute on the clicked button to true.
Set aria-hidden class on the controlled article to false.
Remove the hide class and add the show class to the controlled article.
const buttons = document.querySelectorAll("[aria-haspopup=true]")
const handleClick = (event) => {
const controls = event.target.getAttribute("aria-controls"),
controlled = document.getElementById(controls),
articles = document.querySelectorAll("article");
if (controlled.getAttribute("aria-hidden") === "true") {
articles.forEach(article => {
article.setAttribute("aria-hidden", "true");
article.classList.add("hide");
article.classList.remove("show");
})
buttons.forEach(button => button.setAttribute("aria-expanded", "false"))
event.target.setAttribute("aria-expanded", "true");
controlled.setAttribute("aria-hidden", "false");
controlled.classList.remove("hide");
controlled.classList.add("show");
}
}
buttons.forEach(button => {
button.addEventListener("click", handleClick);
})
ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
}
li {
margin-right: 10px;
}
article {
height: calc(100vh - 50px);
width: 100vw;
position: absolute;
top: 50px;
left: 0;
}
#feature {
background-color: red;
}
#sale {
background-color: green;
}
#view {
background-color: blue;
}
.show {
opacity: 1;
transition: opacity .2s ease-in-out .2s;
}
.hide {
opacity: 0;
transition: opacity .2s ease-in-out;
}
button[aria-expanded=true] {
background-color: #cceeff;
}
<ul>
<li>
<button aria-haspopup="true" aria-expanded="true" aria-controls="feature">Featured</button>
</li>
<li>
<button aria-haspopup="true" aria-expanded="false" aria-controls="sale">On Sale</button>
</li>
<li>
<button aria-haspopup="true" aria-expanded="false" aria-controls="view">Most Viewed</button>
</li>
</ul>
<article class="show" id="feature" aria-hidden="false">
<h1>Featured</h1>
</article>
<article class="hide" id="sale" aria-hidden="true">
<h1>On Sale</h1>
</article>
<article class="hide" id="view" aria-hidden="true">
<h1>Most Viewed</h1>
</article>
This question already has answers here:
CSS-only masonry layout
(4 answers)
Closed last year.
I want to put my photos according to the following plan:
ul {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
ul > li {
width: 49%;
}
ul > li img {
width: 100%;
margin-block-end: 0.25rem;
}
<ul>
<li>
<img src="img/study-image-1.png" alt="">
</li>
<li>
<img src="img/study-img-3.png" alt="">
</li>
<li>
<img src="img/study-img-2.png" alt="">
</li>
<li>
<img src="img/study-img-4.png" alt="">
</li>
</ul>
But when I did my design based on the following code, it was like this.
Thank you in advance for your cooperation
Do you want something like this?, you don´t need javascript
https://codepen.io/marcosefrem/pen/KKXELPy
<ul>
<li>
<img src="https://picsum.photos/500/400" alt="">
</li>
<li>
<img src="https://picsum.photos/100/50" alt="">
</li>
<li>
<img src="https://picsum.photos/200/200" alt="">
</li>
<li>
<img src="https://picsum.photos/100/400" alt="">
</li>
<li>
<img src="https://picsum.photos/500/400" alt="">
</li>
<li>
<img src="https://picsum.photos/100/50" alt="">
</li>
<li>
<img src="https://picsum.photos/200/200" alt="">
</li>
<li>
<img src="https://picsum.photos/100/400" alt="">
</li>
</ul>
<style>
ul {
column-count: 3;
column-gap: 1.25rem;
}
li {
break-inside: avoid-column;
position: relative;
display: inline-block;
width: 100%;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex-direction: column;
}
li img {width:100%; object-fit:cover}
</style>
For this fairly straightforward layout where it must be known that the aspect ratios of the two bigger images are the same as are the aspect ratios of the two smaller images you could use CSS two columns:
ul {
columns: 2;
width: 50vw;
font-size: 4px;
}
li img {
width: 100%;
height: auto;
margin: 2px 0 2px 0;
}
<ul>
<li><img src="https://picsum.photos/id/1016/100/50"></li>
<li><img src="https://picsum.photos/id/1015/200/300"></li>
<li><img src="https://picsum.photos/id/1016/200/300"></li>
<li><img src="https://picsum.photos/id/1015/100/50"></li>
</ul>
Note - the vertical gap depends on font-size, hence the 4px to match the 2x2px of the margins. Obviously you will want to adjust this and the width of the whole thing to suit your particular needs.
Also can use from divs instead ul and li:
.container {
width: 300px;
grid-template-rows: 100px 100px 100px;
display: grid;
grid-template-areas: 'one tow' 'tree tow' 'tree four';
grid-gap: 10px;
}
img {
width: 100%;
height: 100%;
margin-block-end: 0.25rem;
}
.item1 {
grid-area: one;
}
.item2 {
grid-area: tow;
}
.item3 {
grid-area: tree;
}
.item4 {
grid-area: four;
}
<div class="container">
<div class="item1">
<img src="https://s4.uupload.ir/files/7560b48482bfae5c-02b97ffc647f-3822363654_tji3.jpg" alt="">
</div>
<div class="item2">
<img src="https://s4.uupload.ir/files/5c29cf910a706_8m.jpg" alt="">
</div>
<div class="item3">
<img src="https://s4.uupload.ir/files/717195_346_g0du.jpg" alt="">
</div>
<div class="item4">
<img src="https://s4.uupload.ir/files/0.270967001322580170_jazzaab_ir_ajvv.jpg" alt="">
</div>
</div>
I have a navigation bar with a unordered list and multiple items that contains links for the individual pages.
I want a yellow box to appear ontop of the link if i'm on that current page. I made the yellow boxes as you can see and i'm trying to think of the best approach for making the box appear on the concurrent page, any ideas?
Part i'm talking about:
const linkStyle = css`
text-decoration: none;
font-family: "Montserrat";
position: relative;
font-weight: 300;
font-style: normal;
color: ${theme.colors.text};
&::after {
background-color: ${theme.colors.primary};
width: 150%;
height: 40px;
content: "";
position: absolute;
transform: translateX(-50%);
top: -50px;
left: 50%;
}
`;
Full file Header.jsx
import React from "react";
import { css } from "emotion";
import { useTheme } from "emotion-theming";
const Header = () => {
const theme = useTheme();
const headerStyle = css`
position: absolute;
top: 0;
right: 0;
`;
const navStyle = css`
width: 1093px;
position: relative;
background-color: ${theme.colors["bg-nav"]};
display: flex;
justify-content: right;
height: 109px;
`;
const accountStyle = css`
width: 428px;
height: 109px;
background-color: ${theme.colors["alt-red"]};
`;
const ulStyle = css`
box-sizing: border-box;
padding: 0;
display: flex;
margin: 0;
font-size: 1rem;
align-items: center;
list-style: none;
`;
const itemStyle = css`
box-sizing: border-box;
padding: 0 30px;
`;
const linkStyle = css`
text-decoration: none;
font-family: "Montserrat";
position: relative;
font-weight: 300;
font-style: normal;
color: ${theme.colors.text};
&::after {
background-color: ${theme.colors.primary};
width: 150%;
height: 40px;
content: "";
position: absolute;
transform: translateX(-50%);
top: -50px;
left: 50%;
}
`;
return (
<header className={headerStyle}>
<nav className={navStyle}>
<ul className={ulStyle}>
<li className={itemStyle}>
<a className={linkStyle} href="/">
Home
</a>
</li>
<li className={itemStyle}>
<a className={linkStyle} href="/">
Menu
</a>
</li>
<li className={itemStyle}>
<a className={linkStyle} href="/">
Gallery
</a>
</li>
<li className={itemStyle}>
<a className={linkStyle} href="/">
Testiminials
</a>
</li>
<li className={itemStyle}>
<a className={linkStyle} href="/">
Contact Us
</a>
</li>
</ul>
<div className={accountStyle}></div>
</nav>
</header>
);
};
export default Header;
I think it depends on what library you are using for routing because each one does it differently. Assuming you are using the most popular (afaik) React Router library, then it would be a case of using a <NavLink> instead of a <Link>. When the current URL matches the <NavLink> you can add a custom class to activeClassName.
Here’s a link to what I’m referring to: https://github.com/ReactTraining/react-router/tree/master/packages/react-router-dom
With that in mind, here’s a simplified version of what you’d need to do:
import React from "react";
import { css } from "emotion";
import { useTheme } from "emotion-theming";
import { NavLink } from 'react-router-dom';
const Header = () => {
const activeClass = css`
/* active css styles go here */
`;
return (
<header>
<nav>
<ul>
<li>
<NavLink exact to="/" className={linkStyle} activeClassName={activeClass}>
Home
</NavLink>
</li>
<li>
<NavLink to="/menu" className={linkStyle} activeClassName={activeClass}>
Menu
</NavLink>
</li>
</ul>
</nav>
</header>
);
};
export default Header;
I am trying to create a photo gallery app and came across some obstacles. I want to have each image take equal portion of the div, for example if there are two images, each image takes up 50% of the div, and if there are three images, each images takes up 33.33% of the div, etc. Further, is there a way to format those images to be in square dimensions through css?
Also, I have the photos-gallery div that contains h2 and photos-gallery-content div. Currently, I am hardcoding the height for the photos-gallery-content div to fit inside the parent div, but is there a way to make that div take the remainder of the height of its parent div?
Eventually I want the pictures to render dynamically using React so any recommendations/advice on that would help a lot too.
Here is my code:
#photos {
width: 634px;
height: 339px;
}
.photos-gallery {
width: 634px;
height: 275.03px;
}
.photos-gallery-header {
font-size: 24px;
font-weight: bold;
line-height: 32px;
color: #333333;
border-bottom: 1px solid #E1E1E1;
padding-bottom: 16px;
margin: 0 0 16px 0;
display: flex;
justify-content: space-between;
}
.photos-gallery-content {
height: 200px;
}
.photos-gallery-layout {
height: 200px;
overflow: hidden;
float: left;
display: flex;
margin: 0;
padding: 0;
}
.photos-gallery-layout li {
height: auto;
float: left;
list-style: none;
display: flex;
}
.photo {
display: inline-flex;
white-space: nowrap;
}
.photo img {
max-width: 100%;
max-height: auto;
display: inline-block;
vertical-align: middle;
}
<div id="photos-gallery" class="photos content-block">
<h2 class="photos-gallery-header"> 2 Photos </h2>
<div class="photos-gallery-content">
<ul class="photos-gallery-layout">
<li class="photos-gallery-li">
<div class="photo">
<img src="https://i.imgur.com/8pTwPlXb.jpg" />
</div>
</li>
<li class="photos-gallery-li">
<div class="photo">
<img src="https://i.imgur.com/OPAR3PCb.jpg" />
</div>
</li>
<li class="photos-gallery-li">
<div class="photo">
<img src="https://i.imgur.com/A8eQsll.jpg" />
</div>
</li>
</ul>
</div>
<div>
I used your HTML and wrote a little CSS to demonstrate how to:
Have any amount of items fit at equal widths in one row using flexbox (display: flex on the parent and flex: 1 on the children)
Have <img> elements crop to the shape of the tallest element (in this case, a square) using object-fit: cover (note compatibility on CanIUse)
.photos-gallery-layout {
list-style: none;
padding: 0;
margin: 0;
display: flex;
}
.photos-gallery-li {
flex: 1;
}
.photo,
.photo img {
height: 100%;
}
.photo img {
width: 100%;
object-fit: cover;
}
<ul class="photos-gallery-layout">
<li class="photos-gallery-li">
<div class="photo">
<img src="https://i.imgur.com/8pTwPlXb.jpg" />
</div>
</li>
<li class="photos-gallery-li">
<div class="photo">
<img src="https://i.imgur.com/OPAR3PCb.jpg" />
</div>
</li>
<li class="photos-gallery-li">
<div class="photo">
<img src="https://i.imgur.com/A8eQsll.jpg" />
</div>
</li>
</ul>
I have 4 divs with the class .piece-slide that horizontally scroll across the page within the the div #work, which is a flex element. Within the third .piece-slide div the 3 nested elements are absolutely positioned, this renders the width of the third .piece-slide div to 0, so now I want to programmatically set the width of the third .piece-slide div so that it covers the 3 nested elements.
For some reason I am unable to set this width through CSS. I have also tried through jQuery. It would be much appreciated if some pointed me in the right direction as how to rectify this. Here is a jsfiddle as well as the embedded code below.
$("#third-div").outerWidth("100vw");
#wrapper {
display: flex;
flex-direction: column;
height: 100vh;
}
.content {
flex: 1;
}
#work {
height: 100%;
overflow-x: scroll;
display: flex;
background-color: red;
}
.piece-slide {
display: flex;
align-items: center;
position: relative;
padding-right: 5em;
box-sizing: border-box;
border-right: 1px solid black;
}
.piece {
width: 25vw;
margin: 10px;
}
.piece img {
max-width: 100%;
}
#third-div {
/* D0ES NOT WORK */
width: 100vw;
background-color: green;
}
#third-div a {
position: absolute;
}
#third-div a:nth-child(1) {
top: 0;
left: 0;
}
#third-div a:nth-child(2) {
top: 25vw;
left: 25vw;
}
#third-div a:nth-child(3) {
left: 60vw;
}
<div id="wrapper">
<div class="content">
<div id="work">
<div class="piece-slide">
<a class="piece">
<img src="https://athlonecommunityradio.ie/wp-content/uploads/2017/04/placeholder.png">
</a>
</div>
<div class="piece-slide">
<a class="piece">
<img src="https://dummyimage.com/hd1080https://dummyimage.com/hd1080">
</a>
<a class="piece">
<img src="https://dummyimage.com/hd1080https://dummyimage.com/hd1080">
</a>
</div>
<!-- THIRD DIV WHERE WIDTH SHOULD BE SET -->
<div id="third-div" class="piece-slide">
<a class="piece" num="1">
Nested Element 1<img src="http://i.stack.imgur.com/yZlqh.png">
</a>
<a class="piece" num="2">
Nested Element 2<img src="http://www.jennybeaumont.com/wp-content/uploads/2015/03/placeholder.gif">
</a>
<a class="piece" num="3">
Nested Element 3<img src="http://suplugins.com/podium/images/placeholder-02.jpg">
</a>
</div>
<div class="piece-slide">
<a class="piece">
<img src="https://athlonecommunityradio.ie/wp-content/uploads/2017/04/placeholder.png">
</a>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Try to remove
flex-direction: column;
from #wrapper.
Or change it to
flex-direction: row;