I want to show 3 boxes of content (Images + links ) inside a Table inside my SPFx react web part, here is the final result i have:-
I have the following code:-
singlenews.tsx:-
import * as React from 'react';
import styles from './SingleNews.module.scss';
import { ISingleNewsProps } from './ISingleNewsProps';
import NewsTableCell from './NewsTableCell';
export interface INews {
recentNews: ISingleNewsProps[];
featuredNews?: ISingleNewsProps[];
featured: boolean;
}
export default class SingleNews extends React.Component<INews, {}> {
public render(): React.ReactElement<INews> {
const newsTableCells = this.props.recentNews.map((post, index) => {
return (
<NewsTableCell
post={post}
rowspan={index === 0 ? 2 : 1}
/>
);
});
return (
<table>
{this.props.featured ?
<>
<tr>
{ newsTableCells[0] }
{ newsTableCells[1] }
</tr>
<tr>
{ newsTableCells[2] }
</tr>
</>
: null
}
</table>
);
}
}
newstablecell.tsx:-
import * as React from 'react';
import { Icon } from 'office-ui-fabric-react/lib/Icon';
import styles from './SingleNews.module.scss';
import { ISingleNewsProps } from './ISingleNewsProps';
export interface INewsTableCellProps {
post: ISingleNewsProps;
rowspan: number;
}
export default class NewsTableCell extends React.Component<INewsTableCellProps, {}> {
public render(): React.ReactElement<INewsTableCellProps> {
const { post, rowspan } = this.props;
return (
<td rowSpan={rowspan}>
<a
className={styles.singleNews}
href={post.link}
key={post.Title}
>
<div
className={styles.singleNews__image}
style={{ backgroundImage: `url(${post.image})` }}
/>
<div className={styles.singleNews__content}>
<div className={styles.singleNews__content__info}>
<span className={styles.singleNews__content__info__label}>{post.Featured}</span>
<span className={styles.singleNews__content__info__date}>
{post.date}
</span>
</div>
</div>
<div className={styles.singleNews__content}>
<div className={styles.singleNews__content__info}>
{(rowspan===2)?
<h2 className={styles.singleNews__content__info__title__featured}>
{post.Title}
</h2>
:
<h2 className={styles.singleNews__content__info__title}>
{post.Title}
</h2>}
{post.likes ? (
<div
className={styles.singleNews__content__info__reactions}
>
<span
className={
styles.singleNews__content__info__reactions__likes
}
>
<Icon iconName='Like' />
{post.likes}
</span>
<span className={
styles.singleNews__content__info__reactions__comments
}>
<Icon iconName='ActionCenter' />
{post.coments}
</span>
</div>
) : null}
</div>
</div>
</a>
</td>
);
}
}
SingleNews.module.scss:-
#import '~office-ui-fabric-react/dist/sass/References.scss';
#import '../../../../assets/global.module';
.featured {
flex: 2;
}
.secondary {
flex: 1;
display: flex;
flex-direction: column;
gap: 1em;
}
.singleNews {
text-decoration: none;
font-family: $font-family;
font-size: $font-size;
font-weight: $regular-font-weight;
&__image {
padding: 5em;
background-repeat: no-repeat;
background-size: cover;
background-position: center;
&.featured {
height: 75%;
}
}
&__content {
padding: 1em;
background-color: $white;
overflow: hidden;
border: 1px solid $medium-silver;
border-top: none;
display: flex;
flex-direction: column;
&.featured {
height: 25%;
justify-content: flex-start;
}
&__info {
display: flex;
flex-direction: row;
justify-content: space-between;
font-size: 12px;
font-weight: $regular-font-weight;
color: $primary-font-color;
&__title {
font-size: 16px; //22px mob
font-weight: $semiBold-font-weight;
color: $primary-font-color;
max-width: 290px;
min-width: 135px;
margin: 15px 0 0;
word-break: break-word;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
line-height: 23px; /* fallback */
max-height: 46px; /* fallback */
-webkit-line-clamp: 2; /* number of lines to show */
-webkit-box-orient: vertical;
&__featured {
font-size: 22px; //2.33 mobile
font-weight: $semiBold-font-weight;
max-width: 230px;
margin: 15px 0 0;
}
&__first {
font-size: 1.83em; //2.33 mobile
font-weight: $semiBold-font-weight;
max-width: 230px;
margin: 15px 0 0;
}
}
&__date,
&__label {
text-transform: uppercase;
}
&__reactions {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-self: flex-end;
margin-bottom: 5px;
&__likes {
margin-right: 10px;
}
&__likes > i,
&__comments > i {
margin-right: 5px;
}
}
}
}
#media screen and (min-width: 768px) {
&__content {
&__info {
&__title {
max-width: 230px;
&__featured {
font-size: 1.83em; //22px mob
min-width: 380px;
}
}
}
}
}
}
The above is working well, but I only issue I am facing is: how can I expand the first box (cell) to fully occupy the vertical space, as per the arrows I added to the picture?
Related
I am using display: flex to position the contents in a container. When I am minimizing the window size the content goes out of the box. The icon and the button should remain at the center when the center text increases. This is what is being so far.
How can I make the content not to go outside of the box during resizing?
https://codesandbox.io/s/updated-file-upload-forked-gowfyo?file=/src/index.tsx
import * as React from "react";
import { render } from "react-dom";
import "./styles.css";
const App = () => {
return (
<div className="info-box-container">
<div className="info-box-section">
<span className={"info-box-icon"}>icon</span>
<div className={"info-box-text"}>
<span>Dummy Text Dummy Text Dummy Text Dummy Text</span>
</div>
<button className={"info-box-action-button"}>Test Configuration</button>
</div>
</div>
);
};
render(<App />, document.getElementById("root"));
CSS
.info-box-container {
border: 1px solid black;
padding: 8px 20px;
}
.info-box-container .info-box-section {
display: flex;
flex-direction: row;
align-items: center;
}
.info-box-container .info-box-section .info-box-text {
flex: 1;
margin-left: 12px;
}
.info-box-container .info-box-section .info-box-action-button {
float: right;
}
Here is my solution.
This way, you are using row-wrap to wrap the button to a new line.
Change the css as follows:
.info-box-container {
border: 1px solid black;
padding: 8px 20px;
}
.info-box-container .info-box-section {
display: flex;
flex-flow: row wrap;
align-items: center;
}
.info-box-container .info-box-section .info-box-text {
flex: 1;
margin-left: 12px;
}
.info-box-action-button {
display: flex;
overflow: visible;
}
/Navbar.js/
import './navbar.scss';
import {FaBars, FaSearch} from "react-icons/fa";
import { useState } from 'react';
function Navbar(){
const [hide,sethide] = useState(true);
const barIcon = document.querySelectorAll(".link-hide");
const showIcon = () => {
sethide(!hide);
if(!hide){
console.log("hello");
barIcon.forEach(baricon => {
baricon.style.display = "block";
})
}
else{
console.log("hi");
barIcon.forEach(baricon => {
baricon.style.display = "none";
})
}
}
return (
<div className='navbar'>
<ul className='link-group'>
<li className='hello'>Home</li>
<li className='link-hide'>Band</li>
<li className='link-hide'>Tour</li>
<li className='link-hide'>Contact</li>
<li className='link-hide'>More</li>
</ul>
<div className='align-icon'>
<FaSearch className='search-icon'/>
<FaBars className='bar-icon' onClick={showIcon}/>
</div>
</div>
);
}
export default Navbar;
===========================================
/Navbar.scss/
#import url('https://fonts.googleapis.com/css2?family=Freehand&family=Josefin+Sans:wght#200;300;400&family=Montserrat:wght#200;300;400;600&family=Silkscreen&display=swap');
*{
padding : 0px;
margin : 0px;
box-sizing: border-box;
text-align: left;
text-decoration: none;
list-style-type: none;
font-family: 'Montserrat', sans-serif;
font-weight: 600;
color : white;
}
.navbar{
background : black;
display: flex !important;
position: relative;
grid-template-columns: 50% 50%;
position: fixed;
width: 100%;
ul{
li{
padding: 20px 25px;
}
li:hover{
background-color: gray ;
}
}
.align-icon{
align-self: center;
position: absolute;
right: 0px;
padding: 21px 25px;
}
.align-icon:hover{
background-color: gray;
}
}
#media (max-width: 570px){
.search-icon{
display: none;
}
.align-icon{
align-self: flex-start !important;
}
.bar-icon{
display: block;
}
.link-group{
display: block;
width: 100%;
.link-hide{
display: none;
}
li:nth-child(1){
display:inline-block;
}
}
}
#media (min-width: 571px){
ul{
display: flex;
}
.search-icon{
display: block;
}
.bar-icon{
display:none;
}
.link-hide{
display: block !important;
}
}
============================================
/Home.scss/
#import url('https://fonts.googleapis.com/css2?family=Freehand&family=Josefin+Sans:wght#200;300;400&family=Montserrat:wght#200;300;400;600&family=Silkscreen&display=swap');
*{
margin: 0;
padding: 0;
box-sizing: border-box;
color:white;
font-family: 'Montserrat', sans-serif;
}
.show-image{
position: relative;
.pos-absolute{
width: 100%;
position: absolute;
bottom: 10%;
h1,p{
display: flex;
justify-content: center;
}
}
}
.head-text{
font-size: 20px;
}
I am writing code with Reactjs.
My webpage has 2 components which are Navbar.js and Home.js.
When I try to create the class .show-image in home.scss, my navbar is hidden from the web page, and when I remove it, the navbar reappears. Please help me senior.
The DOM in react is not fully-loaded when the component is first rendered so you can't use document.querySelectorAll, instead use a Hook called "useRef".
Code with the fix:
import React, { useRef } from 'react';
import './navbar.scss';
import {FaBars, FaSearch} from "react-icons/fa";
import { useState } from 'react';
function Navbar() {
const [hide, setHide] = useState(true);
const linkHideElements = useRef(null);
const showIcon = () => {
setHide(!hide);
if (!hide) {
linkHideElements.current.forEach(element => {
element.style.display = 'block';
});
} else {
linkHideElements.current.forEach(element => {
element.style.display = 'none';
});
}
};
return (
<div className="navbar">
<ul className="link-group">
<li className="hello">Home</li>
<li className="link-hide" ref={linkHideElements}>Band</li>
<li className="link-hide" ref={linkHideElements}>Tour</li>
<li className="link-hide" ref={linkHideElements}>Contact</li>
<li className="link-hide" ref={linkHideElements}>More</li>
</ul>
<div className="align-icon">
<FaSearch className="search-icon" />
<FaBars className="bar-icon" onClick={showIcon} />
</div>
</div>
);
}
export default Navbar;
I've made a budgeting app that has expenses and Income tabs. Every time you add an expense or income, the app pushes the information inside of an array of objects and dynamically renders an <li> component and places it inside of a <ul>. I'm having trouble with the edit and delete features. Each individual <li> comes with a delete and edit button. The <li>, delete button, and edit button all have the same id of Date.now(). Date.now() is used because it produces a number based on milliseconds and won't produce the same id twice unless someone types an expense or income twice within one millisecond I want to click on the delete button inside of the <li> and have my app remove that individual object from my entry_list[] array and also remove the <li> from the DOM.
'use strict'
const balanceElement = document.querySelector(".balance .value");
const totalIncome = document.querySelector(".income-total");
const totalOutcome = document.querySelector(".outcome-total");
const incomeElement = document.querySelector(".income-tab");
const expense = document.querySelector(".expense-tab");
const all = document.querySelector(".all-tab");
const incomeList = document.querySelector(".income-tab .list");
const expenseList = document.querySelector(".expense-tab .list");
const allList = document.querySelector(".all-tab .list");
const expensesButton = document.querySelector(".tab1");
const incomeButton = document.querySelector(".tab2");
const allButton = document.querySelector(".tab3");
const addExpense = document.querySelector(".add-expense")
const expenseTitle = document.querySelector(".expense-title-input")
const expenseAmount = document.querySelector(".expense-amount-input")
const addIncome = document.querySelector(".add-income")
const incomeTitle = document.querySelector(".income-title-input")
const incomeAmount = document.querySelector(".income-amount-input")
const list = document.querySelector('.list')
//SWITCHING BETWEEN TABS
expensesButton.addEventListener('click', () => {
expense.classList.remove('hidden');
incomeElement.classList.add('hidden');
expensesButton.classList.add('clicked');
incomeButton.classList.remove('clicked');
})
incomeButton.addEventListener('click', () => {
incomeElement.classList.remove('hidden');
expense.classList.add('hidden');
expensesButton.classList.remove('clicked');
incomeButton.classList.add('clicked');
})
incomeList.addEventListener('click', deleteOrEdit)
expenseList.addEventListener('click', deleteOrEdit)
let entry_list = []
addExpense.addEventListener('click', () =>{
if(expenseTitle.value == '' || expenseAmount.value == ''){
return;
}
let expense = {
type: 'expense',
title: expenseTitle.value,
amount: expenseAmount.value,
id: Date.now()
}
entry_list.push(expense)
clearExpense()
changeLists()
})
addIncome.addEventListener('click', () =>{
if(incomeTitle.value == '' || incomeAmount.value == ''){
return;
}
let income = {
type: 'income',
title: incomeTitle.value,
amount: incomeAmount.value,
id: Date.now()
}
entry_list.push(income)
clearIncome()
changeLists()
})
const clearExpense = () =>{
expenseTitle.value = '';
expenseAmount.value = '';
}
const clearIncome = () =>{
incomeTitle.value = ''
incomeAmount.value = ''
}
const changeLists = () =>{
expenseList.innerHTML = ''
incomeList.innerHTML = ''
entry_list.map((entry) =>{
if(entry.type == 'expense'){
return expenseList.innerHTML += `<li id = "${entry.id}" class= "${entry.type}">
<div class = "entry">${entry.title}: $${entry.amount}</div>
<div class="icon-container">
<div class = "edit" id="${entry.id}"></div>
<div class ="delete" id="${entry.id}"></div>
</div>
</li>`
}
else if(entry.type == 'income'){
return incomeList.innerHTML += `<li id = "${entry.id}" class= "${entry.type}">
<div class = "entry">${entry.title}: $${entry.amount}</div>
<div class="icon-container">
<div class = "edit" id="${entry.id}"></div>
<div class ="delete" id="${entry.id}"></div>
</div>
</li>`
}
})
addIncomes()
}
const addIncomes = () =>{
let sum = 0;
let income = 0;
let outcome = 0;
balanceElement.innerHTML = 0
totalIncome.innerHTML = 0
totalOutcome.innerHTML = 0
entry_list.forEach(list =>{
if(list.type == 'expense'){
sum -= list.amount
outcome -= list.amount
}else if(list.type == 'income'){
sum += Number(list.amount)
income += Number(list.amount)
}
balanceElement.innerHTML = '$' + sum
totalIncome.innerHTML = '$' + income
totalOutcome.innerHTML = '$' + outcome
})
}
// // DETERMINE IF BUTTON IS EDIT OR DELETE
function deleteOrEdit(e){
const targetButton = e.target;
const entry = targetButton.parentNode.parentNode;
if(targetButton.classList == ('delete')){
deleteEntry(entry)
}else if(targetButton.classList == ('edit')){
editEntry(entry);
}
}
// //DELETE FUNCTION
const deleteEntry = (entry) =>{
console.log(entry.id)
entry_list.splice(entry.id, 1)
// entry.innerHTML = ''
console.log(entry.id)
addIncomes()
}
// EDIT FUNCTION
const editEntry = (entry) =>{
let Entry = entry_list[entry.id]
if(entry.type == "income"){
incomeAmount.value = Entry.amount;
incomeTitle.value = Entry.title;
}else if(entry.type == "expense"){
expenseAmount.value = Entry.amount;
expenseTitle.value = Entry.title;
}
deleteEntry(entry);
}
#import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght#400;700&family=Raleway:wght#400;700&display=swap');
*{
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Open Sans', sans-serif;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.budget-container{
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
width: 100%;
background-color: #4F98CA;
}
.balance-container{
width: 360px;
height: 470px;
background-color: #50D890;
border-radius: 30px;
margin-right: 100px;
}
.app-title{
color: white;
margin-top: 1rem;
margin-left: 1rem;
}
.month{
color: white;
margin-top: 1rem;
text-align: center;
}
.budget-header{
display: flex;
flex-direction:column;
justify-content: center;
}
.balance{
margin-top: 1rem;
margin-left: 1rem;
}
.title{
color: white;
font-size: 1.25rem;
opacity: .75;
}
.value{
font-size: 1.75rem;
color: white;
font-weight: bold;
margin-left: 1rem;
}
.account{
margin-top: 2.5rem;
margin: 2.5rem 1.5rem 2.5rem 1.5rem;
display: flex;
justify-content: space-between
}
.income-total{
color: white;
text-align: center;
font-size: 1.5rem;
}
.outcome-total{
color: #4F98CA;
text-align: center;
font-size: 1.5rem;
}
/* DASHBOARD */
.budget-dashboard{
display: block;
width: 360px;
height: 470px;
position: relative;
border-radius: 30px;
background-color: white;
}
.dash-title{
margin-top: 2rem;
margin-left: 1rem;
font-size: 1.5rem;
}
.toggle{
margin: 1rem;
display: flex;
cursor: pointer;
}
.toggle .tab2, .tab3{
margin-left: 1rem;
cursor: pointer;
}
.clicked{
font-weight: bold !important;
}
.hidden{
display: none !important;
}
/* EXPENSES TAB */
.expense-tab{
display: flex;
justify-content: center;
}
.expense-input-container{
position: absolute;
top: 400px;
border-top: solid 1px gray;
width: 100%;
}
.expense-amount-input{
width: 125px;
border: none;
outline: none;
font-size: 1.25rem;
}
.expense-title-input{
width: 125px;
border: none;
outline: none;
font-size: 1.25rem;
}
.add-expense{
color: none;
background-color: none;
border: none;
outline: none;
color: inherit;
}
/* INCOME TAB */
.income-tab{
display: flex;
justify-content: center;
}
.income-input-container{
position: absolute;
top: 400px;
border-top: solid 1px gray;
width: 100%;
}
.input{
display: flex;
justify-content: space-between;
align-items: center;
margin: 1rem;
}
.income-amount-input{
width: 125px;
border: none;
outline: none;
font-size: 1.25rem;
}
.income-title-input{
width: 125px;
border: none;
outline: none;
font-size: 1.25rem;
}
.add-income{
color: none;
background-color: none;
border: none;
outline: none;
}
.plus-img{
width: 40px;
}
/* li */
ul{
width: 360px;
height: 255px;
list-style: none;
margin-top:20px;
overflow-x: auto;
}
/* BUTTON ICONS */
.edit{
background-image: url('media/Icons/icons8-edit-48.png');
background-size: contain;
width: 25px;
height: 25px;
background-repeat: no-repeat;
margin-right: 10px;
}
.delete{
background-image: url('media/Icons/icons8-trash-can-48 (2).png');
background-size: contain;
width:25px;
height: 25px;
background-repeat: no-repeat;
}
.income{
width:250px;
height: auto;
padding-left: 20px;
margin-bottom: 10px;;
word-wrap: break-word;
color: black
}
.expense{
width:250px;
height: auto;
padding-left: 20px;
margin-bottom: 10px;;
word-wrap: break-word;
font-family: 'Gilroy Bold';
color: #4F98CA;
}
li{
display: flex;
justify-content: space-between;
width: 100% !important;
padding-right: 20px;
}
.icon-container{
display: flex;
}
#media (max-width:900px){
.budget-container{
display: inline-block;
position: relative
}
.balance-container{
position: absolute;
top: 10%;
left: 25%;
}
.budget-dashboard{
position: absolute;
left: 25%;
top: 40%;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<title>Budgetrr</title>
</head>
<body>
<main class="budget-container">
<section class="balance-container">
<div class="app-title">
<p>Budgetrr</p>
</div>
<h1 class="month">OCTOBER</h1>
<section class="budget-header">
<div class="balance">
<div class="title">
Balance
</div>
<div class="value">
<small>$</small>0
</div>
</div>
<div class="account">
<div class="budget-income">
<div class="title">
Income
</div>
<div class="income-total">
<small>$</small>0
</div>
</div>
<div class="chart"></div>
<div class="budgetoutcome">
<div class="title">
Expenses
</div>
<div class="outcome-total">
<small>$</small>0
</div>
</div>
</div>
</section>
</section>
<section class="budget-dashboard">
<div class="dash-title">Dashboard</div>
<div class="toggle">
<div class="tab1 clicked">Expenses</div>
<div class="tab2">Income</div>
<!-- <div class="tab3 clicked">All</div> -->
</div>
<div class="income-tab hidden">
<ul class="list"></ul>
<div class="income-input-container">
<form class="input">
<input type="text" class="income-title-input" name="title" placeholder="Title">
<input type="number" class="income-amount-input" name="amount" placeholder="$0">
<button type = "button" class="add-income"><img class= "plus-img"src="media/Icons/icons8-add-new-48.png" alt=""></button>
</form>
</div>
</div>
<div class = "expense-tab">
<ul class="list"></ul>
<div class="expense-input-container">
<div class="input">
<input type="text" class="expense-title-input" name="title" placeholder="Title">
<input type="number" class="expense-amount-input" name="amount" placeholder="$0">
<button type="button" class="add-expense"><img class= "plus-img" src="media/Icons/icons8-add-new-48.png" alt=""></button>
</div>
</div>
</div>
</section>
</main>
<script src="JavaScript/budget.js"></script>
</body>
</html>
I've tried to use .splice() but I can't seem to get it to work.
Your entry is an object. And entry has an id property with Date type.
Your delete function calls this:
entry_list.splice(entry.id, 1)
Javascript splice function
function takes number as argument(s).
You should find the id of element you want to delete and get its index. After that you can delete the element with splice method.
Here is how to delete:
// Find the index of object at the given list
const index = entry_list.findIndex(x => x.id === entry.id);
// Starting from index of element to delete, remove 1 element.
entry_list.splice(index, 1);
I've built a ticker/counter animation with basic HTML, CSS and JavaScript and it is working well. This is for a website to show how performance and cashflow has improved when using a service so where I currently have it working and counting up to my target number, I want to append a string onto the end of these targets at the end so instead of (for example), the final target showing 35, I want it to show '35%' or for another element, '2.5x'.
I essentially want to append either a '%' onto the end if its a whole number, and if its a decimal, I want to append a 'x'.
The problem I'm having is that when I try at the end to append one of these strings onto my counter, it ruins everything and just keeps returning 0.01% instead of my target number which is 35, 70, 20 etc.
If I try to add counter.innerText = Math.ceil(count + inc) + '%' for instance, it breaks everything! I've tried to add .toString() to the end too, and then append the '%' but again the same.
These are my files, I'm sure I'm making a silly mistake somewhere so any help would be greatly appreciated!
HTML:
<div class="ticker-container">
<h1 class='ticker-header'>The Superpowers of Inclusion & Diversity are clear</h1>
</div>
<section class='counters'>
<div class='counter-container'>
<div class='num-container'>
<div class="counter" data-target='35'>0</div>
<h4 class='count-subheader'>Better financial performance</h4>
<p class='tick-p'>McKinsey</p>
</div>
<div class='num-container'>
<div class="counter" data-target='70'>0</div>
<h4 class='count-subheader'>More revenue from innovation</h4>
<p class='tick-p'>BCG</p>
</div>
<div class='num-container'>
<div class="counter" data-target='20'>0</div>
<h4 class='count-subheader'>Higher revenue</h4>
<p class='tick-p'>BCG</p>
</div>
<div class='num-container'>
<div class="counter" data-target='2.5'>0</div>
<h4 class='count-subheader'>Higher cashflow per employee</h4>
<p class='tick-p'>HBR</p>
</div>
</div>
</section>
CSS:
#import url('https://fonts.googleapis.com/css2?family=Rubik:wght#400;500;700;');
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Roboto', sans-serif;
background-image: linear-gradient(to right, #923CC7 , #B978E1);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
}
.counter-container {
max-width: 1200px;
margin: 0 auto;
overflow: auto;
}
.ticker-container {
flex: 1;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.ticker-header {
font-size: 48px;
margin-top: 20px;
}
.counters {
padding: 50px 20px;
}
.counter-container {
display: grid;
grid-gap: 40px;
grid-template-columns: repeat(4, 1fr);
text-align: center;
}
.counter {
font-size: 55px;
margin: 10px 0;
background-color: white;
border-radius: 50%;
width: 120px;
height: 120px;
display: flex;
justify-content: center;
align-items: center;
}
.count-subheader {
font-size: 17px;
margin-top: 25px;
}
.tick-p {
color: white;
margin-top: 20px;
}
.num-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#media(max-width: 700px) {
.counter-container {
grid-template-columns: repeat(2, 1fr);
}
}
JavaScript:
const counters = document.querySelectorAll('.counter');
const speed = 200;
const decSpeed = 30;
counters.forEach(counter => {
const updateCount = () => {
const target = +counter.getAttribute('data-target');
const count = +counter.innerText;
const inc = target / speed;
const decInc = target / decSpeed;
if (count < target && target % 1 === 0) {
counter.innerText = Math.ceil(count + inc)
setTimeout(updateCount, 1);
} else if (count < target && target % 1 !== 0) {
counter.innerText = (count + decInc).toFixed(1)
setTimeout(updateCount, 1);
} else {
count.innerText = target;
}
}
updateCount();
})
The problem is this line:
const count = +counter.innerText;
once you add a symbol to the innerText, next time this won't return a proper number (NaN).
You can fix it by removing the symbol part before casting to number:
const count = +counter.innerText.slice(0, -1);
const counters = document.querySelectorAll('.counter');
const speed = 200;
const decSpeed = 30;
counters.forEach(counter => {
const updateCount = () => {
const target = +counter.getAttribute('data-target');
const count = +counter.innerText.slice(0, -1);
const inc = target / speed;
const decInc = target / decSpeed;
if (count < target && target % 1 === 0) {
counter.innerText = Math.ceil(count + inc) + '%'
setTimeout(updateCount, 1);
} else if (count < target && target % 1 !== 0) {
counter.innerText = (count + decInc).toFixed(1) + 'x';
setTimeout(updateCount, 1);
} else {
count.innerText = target;
}
}
updateCount();
})
#import url('https://fonts.googleapis.com/css2?family=Rubik:wght#400;500;700;');
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Roboto', sans-serif;
background-image: linear-gradient(to right, #923CC7, #B978E1);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
}
.counter-container {
max-width: 1200px;
margin: 0 auto;
overflow: auto;
}
.ticker-container {
flex: 1;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.ticker-header {
font-size: 48px;
margin-top: 20px;
}
.counters {
padding: 50px 20px;
}
.counter-container {
display: grid;
grid-gap: 40px;
grid-template-columns: repeat(4, 1fr);
text-align: center;
}
.counter {
font-size: 55px;
margin: 10px 0;
background-color: white;
border-radius: 50%;
width: 120px;
height: 120px;
display: flex;
justify-content: center;
align-items: center;
}
.count-subheader {
font-size: 17px;
margin-top: 25px;
}
.tick-p {
color: white;
margin-top: 20px;
}
.num-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
#media(max-width: 700px) {
.counter-container {
grid-template-columns: repeat(2, 1fr);
}
}
<div class="ticker-container">
<h1 class='ticker-header'>The Superpowers of Inclusion & Diversity are clear</h1>
</div>
<section class='counters'>
<div class='counter-container'>
<div class='num-container'>
<div class="counter" data-target='35'>0</div>
<h4 class='count-subheader'>Better financial performance</h4>
<p class='tick-p'>McKinsey</p>
</div>
<div class='num-container'>
<div class="counter" data-target='70'>0</div>
<h4 class='count-subheader'>More revenue from innovation</h4>
<p class='tick-p'>BCG</p>
</div>
<div class='num-container'>
<div class="counter" data-target='20'>0</div>
<h4 class='count-subheader'>Higher revenue</h4>
<p class='tick-p'>BCG</p>
</div>
<div class='num-container'>
<div class="counter" data-target='2.5'>0</div>
<h4 class='count-subheader'>Higher cashflow per employee</h4>
<p class='tick-p'>HBR</p>
</div>
</div>
</section>
I have a HTML section of Top Bar which is fixed to view port. And another section of slider. These two 2 section are not totally related to each other as they are the same level in DOM tree. But when I edit the default padding of div.col of Slider, it affect the TopBar. It seems top bar is pulled to bottom and right side when padding of Section edited. I have tried my ways but no way help. Could you please advise any suggestion? Thank you so much. You can view live demo at: https://vanminhquangtri.github.io/football-fashion/
The Top Slide:
import React from 'react';
import {NavLink} from "react-router-dom";
import TinySlider from "tiny-slider-react"
const settings = {
items: 1,
nav: false,
autoplay: true
}
const TopSlide = () => {
return (
<section className="top-slide">
<div className="container-fluid">
<div className="row">
<div className="col">
<div className="wrap">
<TinySlider settings={settings}>
<div className="slide-item item-1">
<div className="background-image"></div>
<div className="slide-caption">
<h5 className="title">Always update the latest</h5>
<NavLink
to="/best-sales"
className="link"
>
Discover Now
</NavLink>
</div>
</div>
<div className="slide-item item-2">
<div className="background-image"></div>
<div className="slide-caption">
<h5 className="title">Bring you the champion's fashion</h5>
<NavLink
to="/champion"
className="link"
>
Discover Now
</NavLink>
</div>
</div>
<div className="slide-item item-3">
<div className="background-image"></div>
<div className="slide-caption">
<h5 className="title">Top-five leagues in the world</h5>
<NavLink
to="/all-fashion"
className="link"
>
Discover Now
</NavLink>
</div>
</div>
</TinySlider>
</div>
</div>
</div>
</div>
</section>
);
};
export default TopSlide;
The TopBar:
// top bar of web page
import React from 'react';
import {NavLink} from "react-router-dom";
import Logo from "../../Assets/images/section-top-bar/ball.png";
import Leagues from "../../Assets/images/section-top-bar/leagues.jpg";
import HotDeal from "../../Assets/images/section-top-bar/hotdeal.png";
const TopBar = () => {
return (
<section className="top-bar">
<div className="container-fluid">
<div className="row">
{/* ball icon */}
<div className="col-3 ball-icon">
<div className="wrap">
<NavLink
to="/"
exact={true}
>
<img
src={Logo}
alt="ball-icon"
/>
</NavLink>
</div>
</div>
{/* icons of top-5 leagues */}
<div className="col-6 leagues-icon">
<div className="wrap">
<NavLink
to="/most-concerned"
exact={true}
>
<img
src={Leagues}
alt="leagues-icon"
/>
</NavLink>
</div>
</div>
{/* hot deals icon */}
<div className="col-3 top-bar-hot-deals">
<div className="wrap">
<NavLink
to="/hot-deal"
exact={true}
>
<img
src={HotDeal}
alt="leagues-icon"
/>
</NavLink>
</div>
</div>
</div>
</div>
</section>
);
};
export default TopBar;
CSS:
/*--- top bar ---*/
.top-bar {
z-index: 2000;
position: fixed;
left: 0;
bottom: 0;
right: 0;
width: 100%;
border-top: 1px solid rgb(235, 235, 235);
background: white;
.container-fluid {
.row {
.wrap {
width: 100%;
a {
display: block;
width: 100%;
}
img {
height: 30px;
}
}
.col-3.ball-icon {
display: flex;
align-items: center;
justify-content: flex-start;
padding-left: 5px;
img {
width: 30px;
}
}
.col-6.leagues-icon {
text-align: center;
img {
height: 35px;
}
}
.col-3.top-bar-hot-deals {
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 5px;
img {
width: 100%;
}
}
}
}
}
/*--- end top bar ---*/
Slider:
/*--- top slide ---*/
.top-slide {
margin-top: 10px;
.container-fluid {
.row {
.col {
padding: 0; PROBLEM HERE, IF REMOVE THIS TOP BAR WILL BE NOT AFFECTED, BUT I NEED TO KEEP THIS SO THAT IT LOOKS BETTER IN MOBILE
.wrap {
.tns-outer {
> button {
display: none;
}
position: relative;
/* next and back button of slide */
.tns-controls {
z-index: 100;
position: absolute;
top: 40%;
width: 100%;
padding: 0 5px;
display: flex;
justify-content: space-between;
button {
border: none;
outline: none;
background: transparent;
color: transparent;
width: 20px;
height: 20px;
background : {
size: cover;
position: center;
repeat: no-repeat;
}
}
button[data-controls=prev] {
background-image: url("../src/Assets/images/section-top-slide/previous-3.png")
}
button[data-controls=next] {
background-image: url("../src/Assets/images/section-top-slide/next-3.png")
}
}
.tns-ovh {
.tns-inner {
.tns-slider {
/* each item of slider is a div named slide-item */
.slide-item {
.background-image {
height: 150px;
background: {
position: center 0;
repeat: no-repeat;
size: cover;
}
}
.slide-caption {
text-align: center;
.title {
font-weight: bold;
font-size: 16px;
margin-bottom: 0;
}
.link {
color: white;
background: $color-red;
display: inline-block;
padding: 2px 5px;
border-radius: 3px;
font-size: 14px;
font-weight: bold;
}
}
}
.slide-item.item-1 {
.background-image {
background-image: url("../src/Assets/images/section-top-slide/tot.webp")
}
}
.slide-item.item-2 {
.background-image {
background-image: url("../src/Assets/images/section-top-slide/arsenal.jpg")
}
.title {
text-shadow: 1px 1px 3px $color-red;
}
}
.slide-item.item-3 {
.background-image {
background-image: url("../src/Assets/images/section-top-slide/mc.jpg")
}
.title {
text-shadow: 1px 1px 3px #5fa5e3;
}
}
}
}
}
}
}
}
}
}
}
/*--- end top slide ---*/