Overlapping avatars: convert SCSS to CSS and PUG to HTML - javascript

I'm trying to create overlapping avatars in HTML and CSS. It is based on this code snippet. Only that this snippet is created in SCSS and PUG. How can I convert PUG to HTML and SCSS to CSS? I have a problem that the avatars are distant from each other and the name does not appear when you hover over the avatar.
Check code here.
import React from 'react';
import { render } from 'react-dom';
import './style.css';
class App extends React.Component {
constructor() {
super();
this.state = {
todos:
[
{name:'Tobias', avatar: 'https://vignette.wikia.nocookie.net/arresteddevelopment/images/7/77/2x01_The_One_Where_Michael_Leaves_%28098%29.png/revision/latest?cb=20121126025806'},
{name:'Lindsey', avatar: 'https://vignette.wikia.nocookie.net/arresteddevelopment/images/1/16/Season_3_Character_Promos_-_Lindsay_Bluth_F%C3%BCnke_01.jpg/revision/latest?cb=20111027201233'},
{name:'Buster', avatar: 'https://vignette.wikia.nocookie.net/arresteddevelopment/images/b/be/Season_3_Character_Promos_-_Buster_Bluth_01.jpg/revision/latest?cb=20111027201440'},
{name:'George Michael', avatar: 'https://vignette.wikia.nocookie.net/arresteddevelopment/images/c/c3/Season_1_Character_Promos_-_George_Michael_Bluth_02.jpeg/revision/latest?cb=20120429230332'},
{name:'Gob', avatar: 'https://vignette.wikia.nocookie.net/arresteddevelopment/images/0/02/Season_1_Character_Promos_-_G.O.B.jpeg/revision/latest?cb=20120429230530'},
{name:'Michael', avatar: 'https://vignette.wikia.nocookie.net/arresteddevelopment/images/1/10/1x01_Pilot_%2839%29.png/revision/latest?cb=20120301050056'}
],
};
}
render() {
let todos = this.state.todos.map((todo, index) =>
<Todo
key={index}
index={index}
todo={todo}
/>
)
return (
<div>
<ul>{todos}</ul>
</div>
);
}
}
class Todo extends React.Component {
render() {
const Background = this.props.todo.avatar;
const name = this.props.todo.name;
const profile = {
"&:hover&:after": {
position: "absolute",
content: `attr(${name})`,
background: "rgba(255, 255, 255, .95)",
color: "inherit",
fontSize: "10px",
padding: "4px",
width: "auto",
bottom: "-0.5rem",
right: "-0.5rem",
boxShadow: "0px 5px 12px rgba(0, 0, 0, .12)",
opacity: "0",
borderRadius: "0.15rem",
animation: "fade 100ms ease 750ms forwards"
}
}
return (
<ul className="c-profile__list">
<li style={profile} className="c-profile" style={{backgroundImage: `url(${Background})`}}></li>
</ul>
);
}
}
render(<App />, document.getElementById('root'));
CSS
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
html, body {
width: 100%;
height: 100%;
}
body {
display: flex;
align-items: center;
justify-content: center;
font-family: system-ui;
flex-direction: column;
color: #2c2c54;
font-size: 1.6rem;
}
.c-profile {
width: 70px;
height: 70px;
border: 4px solid white;
border-radius: 50%;
box-shadow: 0px 3px 8px rgba(44, 44, 84, .2);
display: inline-block;
background: white;
cursor: pointer;
background-size: cover;
background-position: center center;
transition: all 200ms ease;
}
.c-profile:nth-of-type(n+2) {
margin-left: -42px;
}
.c-profile:hover {
transform: scale(1.2);
box-shadow: 0px 8px 20px rgba(44, 44, 84, .2);
}
.c-profile:hover:after {
position: absolute;
content: attr(username);
background: rgba(255, 255, 255, .95);
color: inherit;
font-size: 10px;
padding: 4px;
width: auto;
bottom: -0.5rem;
right: -0.5rem;
box-shadow: 0px 5px 12px rgba(0, 0, 0, .12);
opacity: 0;
border-radius: 0.15rem;
animation: fade 100ms ease 750ms forwards;
}
.c-profile__list {
display: flex;
position: relative;
width: auto;
padding-top: 1rem;
padding-bottom: 1rem;
}
.c-profile__list:hover .c-profile:nth-of-type(n+2) {
margin-left: 7px;
}
article {
width: 100%;
max-width: 600px;
}
#keyframes fade {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
ul {
list-style: none;
display: inline;
}

From a short look...
You are wrapping ul tags in a parent ul. Quick fix:
https://stackblitz.com/edit/react-ctuy4n?file=index.js

In your Todo, you need to remove the additional <ul> tag around each item and add your name as a title prop:
return (
<li style={profile} className="c-profile" title={name} style={{backgroundImage: `url(${Background})`}}></li>
);

Related

How can I make this toggle switch responsive?

I'm trying to make (using React) a toggle switch I found responsive so that I can put it in my app but I'm having trouble refactoring it to resize based on content inside and device width/height.
import { useState } from "react";
import styles from "./ToggleSwitch.module.css";
export default function ToggleSwitch({ choice1, choice2 }) {
const [value, setValue] = useState(choice2);
function handleClick() {
setValue(value => (value === choice1 ? choice2 : choice1));
}
function styleToggleSwitch(value) {
if (value === choice1) {
return { clipPath: "inset(0 0 0 50%)", backgroundColor: "#eb9b30" };
} else {
return { clipPath: "inset(0 50% 0 0)", backgroundColor: "#1464cf" };
}
}
return (
<div id={styles["container"]} onClick={handleClick}>
<div className={styles["inner-container"]}>
<div className={styles["toggle"]}>
<p>{choice2}</p>
</div>
<div className={styles["toggle"]}>
<p>{choice1}</p>
</div>
</div>
<div
className={styles["inner-container"]}
style={
value === choice1
? styleToggleSwitch(choice1)
: styleToggleSwitch(choice2)
}
>
<div className={styles["toggle"]}>
<p>{choice2}</p>
</div>
<div className={styles["toggle"]}>
<p>{choice1}</p>
</div>
</div>
</div>
);
}
#import url("https://fonts.googleapis.com/css?family=Asap:400,500,700");
#container {
width: 160px;
height: 36px;
margin: auto;
position: relative;
border-radius: 0.5rem;
overflow: hidden;
user-select: none;
cursor: pointer;
font-family: "Asap", sans-serif;
}
.inner-container {
position: absolute;
left: 0;
top: 0;
width: inherit;
height: inherit;
text-transform: uppercase;
font-size: 0.6em;
letter-spacing: 0.2em;
}
.inner-container:first-child {
background: #e9e9e9;
color: #a9a9a9;
}
.inner-container:nth-child(2) {
background: dodgerblue;
color: white;
clip-path: inset(0 50% 0 0);
transition: 0.3s cubic-bezier(0, 0, 0, 1);
}
.toggle {
width: 50%;
position: absolute;
height: inherit;
display: flex;
box-sizing: border-box;
}
.toggle p {
margin: auto;
}
.toggle:nth-child(1) {
right: 0;
}
When I select the toggle switch buttons they get either the .first or .second class to change their styles. Sorry for using pastebin but Stack Overflow wouldn't allow me to post this much code. Thanks for the help in advance!

Style Element Inside of Component with CSS and React.js

I am trying to make a button that allows the user to switch between light and dark theme. The method I am using is to change the className of my App div. All of the other components in my project are inside of the App component. Then in the individual CSS files for the components I first select the className of the App div which is either .light or .dark. Then I write the name of the component that I want to set a theme color to. For example:
.light p {
background-color: white;
}
However, this doesn't work.
Here are some of the files:
/*App.js*/
import { useState } from "react";
import TaskPage from "./pages/taskPage";
import { fas } from "#fortawesome/free-solid-svg-icons";
import { library } from "#fortawesome/fontawesome-svg-core";
import { MainContextProvider } from "./store/MainContext";
library.add(fas);
function App() {
const [theme, setTheme] = useState("light");
const switchTheme = () => {
setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light"));
};
return (
<MainContextProvider>
<div className={`App ${theme}`}>
<div className="pageTop">
<h1 className="title">Task Board</h1>
</div>
<button className="button" onClick={switchTheme}>
Change theme
</button>
<TaskPage />
</div>
</MainContextProvider>
);
}
export default App;
/*index.css*/
#import url("https://fonts.googleapis.com/css2?family=Roboto:wght#400;500;700&display=swap");
.App {
overflow-x: hidden;
padding-bottom: 40px;
height: 100%;
width: 100%;
}
.light {
background-color: #fcfcfc;
}
.dark {
background-color: #181A1B;
}
.title {
font-family: "Roboto", sans-serif;
font-size: 50px;
font-weight: 700;
text-align: center;
margin-top: 40px;
text-shadow: 0px 3px 4px rgba(0, 0, 0, 0.2);
}
.light .title {
color: black;
}
.dark .title {
color: white;
}
.pageTop {
margin-bottom: 50px;
}
/*todo.module.css*/
.taskCard {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
transition: 0.3s;
width: 340px;
height: 260px;
min-width: 340px;
min-height: 260px;
display: flex;
flex-wrap: wrap;
flex-direction: column;
border-radius: 12px;
padding: 14px;
box-sizing: border-box;
}
.light .taskCard {
background-color: white;
}
.dark .taskCard {
background-color: #2B2E30;
}
I used this sandbox as an example: https://codesandbox.io/s/stupefied-jackson-0ynz6?file=/src/App.js
I am a beginner with React.js

Selecting an element by the class name after insertAdjacentHTML

So when I click my start button, this function is working and I can see it
const displayFirstQuestion = () => {
main.insertAdjacentHTML("afterbegin",
`<div class="question-container">
<h2 class="question-tag">QUESTION 1</h2>
<h3 class="question">
What is the keyword to define a variable that can be modified?
</h3>
<div class="choices">
<p class="choice">A. Function</p>
<p class="choice">B. Const</p>
<p class="choice correct">C. Let</p>
<p class="choice">D. Var</p>
</div>
Next Question >>
</div>` );
};
So I want to select the element with 'correct' classname but it doesn't work. When I print it to the console, it says 'null' basically.
document.querySelector('.correct') // this is null
I tried to put the selector after inserting Html and other different places. It always says null.
Here is the codepen link:
https://codepen.io/raskolnikovcykakekw/pen/mdrvVqX
I just tried you code on browser console and it worked. I just had to close the template string in the 2nd arg of insertAdjacentHTML. Can you provide more info?
Update
Ok, I see. The problem is you are querying and registering events on elements when they aren't in the DOM yet. So, I'd suggest to:
Wrap the loop for registering .choice event listeners in a function and call it right after call displayFirstQuestion;
Query .correct and .nextButton inside answering function.
Something like this:
"use strict";
const main = document.querySelector(".main");
const container = document.querySelector(".container");
const startButton = document.querySelector(".start-button");
const questionContainer = document.querySelector(".question-container");
const choice = [...document.querySelectorAll(".choice")];
const correct = document.querySelector(".correct");
const nextButton = document.querySelector(".next-button");
const endingContanier = document.querySelector(".ending");
////////////////----------------------//////////////---------SELECTING QUESTIONS ---------//////
const displayFirstQuestion = () => {
main.insertAdjacentHTML(
"afterbegin",
`<div class="question-container">
<h2 class="question-tag">QUESTION 1</h2>
<h3 class="question">
What is the keyword to define a variable that can be modified?
</h3>
<div class="choices">
<p class="choice">A. Function</p>
<p class="choice">B. Const</p>
<p class="choice correct">C. Let</p>
<p class="choice">D. Var</p>
</div>
Next Question >>
</div>`
);
};
startButton.addEventListener("click", () => {
container.style.animation = "hidden 1s forwards";
setTimeout(() => {
container.remove();
}, 500);
setTimeout(displayFirstQuestion(), 501);
setTimeout(registerEventListeners(), 600);
});
//////////////////////////////////
const answering = function (element) {
const correct = document.querySelector(".correct");
if (!element.target.classList.contains("correct")) {
element.target.style.background = "red";
correct.style.background = "green";
} else {
correct.style.background = "green";
}
setTimeout(() => {
const nextButton = document.querySelector(".next-button");
nextButton.style.animation = "come-out 0.5s ease";
nextButton.style.display = "inline";
}, 300);
choice.forEach((e) => e.removeEventListener("click", answering));
};
const registerEventListeners = function() {
const choice = document.querySelectorAll(".choice");
choice.forEach(function (e) {
e.addEventListener("click", answering);
});
console.log(correct);
}
* {
margin: 0;
box-sizing: border-box;
}
body {
font-family: "Source Code Pro", monospace;
background: rgba(0, 0, 0, 0.685);
}
a {
text-decoration: none;
color: white;
}
h2 {
background: #323330;
padding: 0.5rem;
border: 1px solid #323330;
border-radius: 10px;
margin-bottom: 30px;
}
.container {
color: white;
display: flex;
flex-direction: column;
align-items: center;
margin: 15rem 0 0 0;
animation: come-out 1s forwards;
}
.start-button {
font-family: "Source Code Pro", monospace;
font-weight: 700;
width: 250px;
height: 55px;
font-size: 1.6rem;
color: #323330;
background: rgb(240, 219, 79);
margin: 2rem;
cursor: pointer;
border-bottom: 5px solid rgb(211, 191, 59);
border-left: 5px solid rgb(211, 191, 59);
border-right: 5px solid rgb(211, 191, 59);
border-top: 1px solid rgb(211, 191, 59);
transition: all 0.3s ease;
border-radius: 10px;
}
.start-button:hover {
color: rgb(240, 219, 79);
background: #323330;
border: 5px solid #323330;
}
.start-button:active {
transform: translate(5%);
}
.question-container {
color: white;
display: flex;
flex-direction: column;
align-items: center;
margin: 5rem 0 0 0;
line-height: 3rem;
font-size: 1.1rem;
animation: come-out 1s forwards;
}
.question {
margin: 0 0 3% 0;
text-align: center;
}
.choices {
flex-direction: column;
}
.choice {
cursor: pointer;
padding: 0 10px 0 10px;
margin-bottom: 10%;
background: rgba(0, 0, 0, 0.432);
border: 1px solid black;
border-radius: 12px;
box-shadow: 1px 1px 6px black;
transition: all 0.5s ease;
text-align: center;
}
.choice:hover {
background: rgba(0, 0, 0, 0.232);
}
.choice:active {
background: rgba(240, 218, 79, 0.229);
transform: translate(5%);
}
.choice-align-left {
text-align: left;
}
.next-button {
position: absolute;
top: 65%;
font-size: 20px;
height: 8vh;
font-family: "Source Code Pro", monospace;
color: white;
cursor: pointer;
margin-right: 15%;
background: rgba(0, 0, 0, 0.432);
border: 1px solid black;
border-radius: 5px;
box-shadow: 1px 1px 6px black;
align-self: flex-end;
display: none;
transition: all 0.5s ease;
}
.next-button:hover {
background: rgba(0, 0, 0, 0.232);
}
.next-button:active {
transform: translate(5%);
}
.back-button {
height: 3rem;
width: 20rem;
}
#keyframes hidden {
0% {
opacity: 1;
}
100% {
display: none;
opacity: 0;
}
}
#keyframes come-out {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.q2-green {
color: rgba(86, 221, 86, 0.596);
}
.q2-yellow {
color: yellow;
}
<body>
<main class="main">
<div class="container">
<h1>
WELCOME TO
<img src="logo.png" alt="js-logo" width="50px" height="50px" /> QUIZ
</h1>
<button class="start-button">LET'S START</button>
</div>
</main>
<script src="script.js"></script>
</body>
Then you can clean up a bit some code.

How do I make this Hover effect on a Card component?

I want to make a hover effect over a Card component that shows more information but I tried a lot of codepen's and videos but it doesn't work for me.
import React, { Component } from 'react'
import '../styles/Project.css'
class Project extends Component {
render() {
return (
<div className="Project-card">
<img
className="Project-card-image"
src={this.props.image}
alt={this.props.title}
/>
<div className="display-over">
<div className="Project-card-libraries">
{this.props.libraries.map((prop) => (
<img
src={prop.image}
alt={prop.name}
className="Project-card-library-images"
/>
))}
</div>
</div>
</div>
)
}
}
.Project-card {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 60%;
height: 100%;
border-radius: 1em;
margin-top: 1em;
align-self: center;
border-radius: 15px;
transition: 0.4s ease-out;
box-shadow: 0px 7px 10px rgba(0, 0, 0, 0.5);
position: relative;
}
.display-over {
position: relative;
display: block;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
color: #fff;
opacity: 0;
transition: all 0.3s ease-in-out;
box-sizing: border-box;
}
.Project-card:hover .display-over {
opacity: 1;
}
.Project-card-image {
width: 100%;
object-fit: cover;
border-radius: 15px;
height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Example I want the red container to be over the whole green container.
I have this. I don't want that white space there which is the div with classname - display-over.
I need that content to be displayed over the image.

How do you start new row on left with dynamic content in Reactjs?

I am working on a personal portfolio page using ReactJS. I am currently trying to create a project page that has rows of flipping cards, however, whenever the cards reach their max-width and move to the next line the card always starts in the center of the page when it needs to start on left. I have tried creating a row wrapper to float: left which breaks the application and a multitude of other ways but I would like to see the best way to create dynamic rows and columns from a mapped array and start new rows from the left. added an image to highlight the issue
Projects.js
import React, { Fragment } from 'react';
import Card from '../common/Card/Card';
import { PROJECTS } from "../../shared/constants/projects";
import "./projects.scss";
const Projects = () => {
return (
<Fragment>
<div className="grid">
{
PROJECTS.map((project, i) => {
return (
<Card animatedCard={true} project={project} key={i} />
)
})
}
</div>
</Fragment>
)
}
export default Projects;
projects.scss
.grid {
width: 60%;
text-align: center;
margin: 0 20% 0 20%;
}
Card.js
import React, { Fragment } from 'react';
import CardFront from './CardFront';
import "./card.scss";
import CardBack from './CardBack';
const Card = props => {
return (
<Fragment>
{props.animatedCard ?
<div className="card-container">
<div className="card-body">
<CardBack project={props.project}/>
<CardFront project={props.project} />
</div>
</div> : null
}
</Fragment>
)
}
card.scss
.button-wrapper {
height: 200px;
bottom: 0;
}
.card-container {
display: inline-block;
position: relative;
z-index: 1;
margin: 50px 25px 0px 25px;
width: 300px;
height: 400px;
perspective: 1000px;
}
.card-body {
width: 100%;
height: 100%;
background-color: white;
transform-style: preserve-3d;
transition: all 0.5s linear;
}
.card-container:hover .card-body {
transform: rotateY(180deg);
}
.card-container:hover > .card-body > .side-front {
opacity: 0;
visibility: hidden;
transition: opacity 1s ease-in, visibility 0.75s linear;
}
.card-side {
position: absolute;
top: 0;
overflow: hidden;
width: 100%;
height: 100%;
color: #8e8d8a;
backface-visibility: hidden;
font-family: sans-serif;
text-align: center;
box-shadow: 0 10px 35px rgba(50, 50, 93, 0.1), 0 2px 15px rgba(0, 0, 0, 0.07);
}
.card-header-img {
max-width: 100%;
max-height: 123px;
margin: 0;
padding: 0;
}
.card-technologies {
list-style: none;
width: 70%;
}
.card-technologies-item {
border-bottom: 1px solid #eee;
margin-bottom: 15px;
padding: 0.75rem;
}
.description {
margin: 30px 20px 20px 20px;
font-size: 18px;
font-weight: 400;
height: 240px;
}
.side-front [class^="col-xs"]:first-of-type {
padding-left: 0;
}
.side-back {
z-index: 2;
text-align: center;
transform: rotateY(180deg);
}
This is happening since you are using text-align: center; in your .grid css.
If you remove it all the cards in the row should start at the left end of the row:
.grid {
width: 60%;
margin: 0 20% 0 20%;
}
Another alternative would be making your .grid a flexbox:
.grid {
width: 60%;
margin: 0 20% 0 20%;
display: flex;
flex-wrap: nowrap;
}

Categories