I want to implement carousel using data from my Vidoes Array, i am unable to obtain desired output instead all the videos in the Array are rendered at the same time
<div id="carouselExampleSlidesOnly" class="carousel slide" data-bs-ride="carousel">
<div class="carousel-inner">
{Videos}
</div>
</div>
This is my Videos array
const Videos = VIDEOS.map((vid) => {
if(vid.name=="Video1"){
vari=true;
}
return (
<div
className={vari?"carousel-item active":"carousel-item"}
style={{ width: "25vw", height: "5vh", background: "#F1F1F1",margin:"auto" }}
>
<img src="..." class="card-img-top" alt={vid.name}></img>
</div>
);
});
I've done just this a couple of days ago.. Have yet to shorten, optimize and add video support though
here's my code:
import React, { useEffect, useState } from 'react';
import "./MediaViewer.css";
import { useGlobalObj, globalObj } from 'logic/zergski-global-object';
// content JSON
import { mediaJSON } from 'logic/content-collections';
// components
import Anchor from 'shared/Anchor';
let current = 'can1';
let canvas = {
can1: {
pos: 'center',
trans: true,
source: mediaJSON[0].src,
},
can2: {
pos: 'right',
trans: true,
source: mediaJSON[1].src,
},
can3: {
pos: 'left',
trans: false,
source: mediaJSON[mediaJSON.length-1].src,
}
}
// iterator
// TODO! add settings
const iterator = ( array, setState, initIndex ) => {
let index = initIndex;
let count = array.length - 1; // content count
let nextSource = index+2; // next imagesource to load
let nextCanvas = 0; // canvas position
let nextImageSource = nextCanvas - 1;
return {
next() {
index = index === count ? 0 : ++index;
nextSource = index+1 > count ? 0 : index+1;
Object.entries(canvas).forEach( c => {
canvas[c[0]].pos = c[1].pos === 'center' ? 'left' : c[1].pos === 'right' ? 'center' : 'right';
c[1].pos === 'center' && (current = c[0]);
if ( c[1].pos === 'right' ) {
canvas[c[0]].trans = false;
canvas[c[0]].source = mediaJSON[nextSource].src;
} else {
canvas[c[0]].trans = true;
}
});
setState({
...canvas,
counter: index+1,
});
},
prev() {
index = index === 0 ? count : --index;
nextSource = index-1 < 0 ? count : index-1;
Object.entries(canvas).forEach( c => {
canvas[c[0]].pos = c[1].pos === 'center' ? 'right' : c[1].pos === 'left' ? 'center' : 'left';
c[1].pos === 'center' && (current = c[0]);
if ( c[1].pos === 'left' ) {
canvas[c[0]].trans = false;
canvas[c[0]].source = mediaJSON[nextSource].src;
} else {
canvas[c[0]].trans = true;
}
});
setState({
...canvas,
counter: index+1,
});
}
}
}
var lastTouch = 0;
var content = Object.create(null);
// component for viewing images, videos and documents
const MediaViewer = props => {
const mediaViewer = {
display: 'hidden',
contentIndex: 0,
initialState: { display: 'hidden' },
}
const [ viewerState, setViewerState ] = useGlobalObj({ mediaViewer });
const [ state, setState ] = useState({
...canvas,
counter: 1,
});
const [ touchState, setTouchState ] = useState({
touch: false,
movement: 0,
});
if ( viewerState.display === 'show' ) {
document.body.classList.add('scroll-lock');
setTimeout(()=>{
globalObj.mediaViewer.setState({ display: 'visible' });
}, 50)
}
useEffect(() => {
const { display, index } = viewerState;
if ( display === 'show' ) {
content = iterator( mediaJSON, setState, index );
current = 'can1';
canvas = {
can1: {
pos: 'center',
trans: false,
source: mediaJSON[index].src,
},
can2: {
pos: 'right',
trans: false,
source: mediaJSON[index === mediaJSON.length-1 ? 0 : index+1].src,
},
can3: {
pos: 'left',
trans: false,
source: mediaJSON[index === 0 ? mediaJSON.length-1 : index-1].src,
}
}
setState({
...canvas,
counter: index+1,
})
}
}, [viewerState]);
const handleClose = () => {
globalObj.mediaViewer.setState({ display: 'hide' });
setTimeout(()=>{
globalObj.mediaViewer.setState({ display: 'hidden' });
}, 400)
document.body.classList.remove('scroll-lock');
}
// input handlers
const handleMovement = ( delta, touch=false ) => {
let nextMovement = touchState.movement - delta;
canvas[current].trans = false;
canvas[current].movement = nextMovement;
setTouchState({ movement: nextMovement });
}
// touch
const handleTouchStart = (e) => {
lastTouch = e.nativeEvent.touches[0].clientX;
}
const handleTouchMove = (e) => {
const delta = lastTouch - e.nativeEvent.touches[0].clientX;
lastTouch = e.nativeEvent.touches[0].clientX;
handleMovement(Math.floor(delta), true);
}
const handleTouchEnd = (e) => {
touchState.movement < -50 ? content.next() : touchState.movement > 50 && content.prev();
lastTouch = 0;
canvas[current].trans = true;
setTouchState({ movement: 0 });
}
return (
<div className={ `Media-Viewer ${ viewerState.display }` }
onTouchStart={ handleTouchStart }
onTouchMove={ handleTouchMove }
onTouchEnd={ handleTouchEnd }
>
<img className={ `Media-Viewer-Content ${ state.can1.pos }` } alt={ '' }
src={ state.can1.source }
style={{
transform: current === 'can1' ? `translateX(${ touchState.movement }px)` : '',
transitionDuration: `${ canvas.can1.trans ? '' : '0s' }`,
}}
/>
<img className={ `Media-Viewer-Content ${ state.can2.pos }` } alt={ '' }
src={ state.can2.source }
style={{
transform: current === 'can2' ? `translateX(${ touchState.movement }px)` : '',
transitionDuration: `${ canvas.can2.trans ? '' : '0s' }`,
}}
/>
<img className={ `Media-Viewer-Content ${ state.can3.pos }` } alt={ '' }
src={ state.can3.source }
style={{
transform: current === 'can3' ? `translateX(${ touchState.movement }px)` : '',
transitionDuration: `${ canvas.can3.trans ? '' : '0s' }`,
}}
/>
<div className="Modal-User-Interface-Wrapper">
<div className="Information-Box">
<h4>{ `${ state.counter }/${ mediaJSON.length }` }</h4>
</div>
<Anchor
altClass="icon"
fileName="cross.svg"
style={{ position: 'absolute', top: '0', right: '0', opacity: '.5' }}
clicked={ handleClose }
/>
<Anchor
altClass="icon"
fileName="arrow.svg"
style={{ transform: 'rotate(180deg)' }}
clicked={ ()=>content.prev() }
/>
<Anchor
altClass="icon"
fileName="arrow.svg"
clicked={ ()=>content.next() }
/>
</div>
</div>
);
}
export default MediaViewer;
And CSS
.Media-Viewer {
display: flex;
position: fixed;
justify-content: space-around;
align-items: center;
height: calc(100*var(--vh));
width: 100vw;
height: 100vh;
top: 0; left: 0;
overflow: hidden;
z-index: 10;
transition: opacity .4s ease;
}
.Media-Viewer.hide,
.Media-Viewer.show {
opacity: 0;
}
.Media-Viewer.hidden {
display: none;
}
.Media-Viewer-Content {
display: flex;
position: absolute;
height: 100%;
width: 100%;
object-fit: contain;
top: 0; left: 0;
z-index: 9;
transition: transform .4s ease;
will-change: transform;
}
.Media-Viewer-Content.center {
transform: translate3d(0,0,0);
}
.Media-Viewer-Content.right {
transform: translate3d(100vw,0,0);
}
.Media-Viewer-Content.left {
transform: translate3d(-100vw,0,0);
}
.Modal-User-Interface-Wrapper {
display: flex;
position: relative;
justify-content: space-between;
align-items: center;
width: calc( 100vw - (100vw - 300px) / 10 );
opacity: .6;
height: calc(100*var(--vh));
z-index: 10;
transition: opacity 1.2s ease;
transition-delay: 4s;
}
.Media-Viewer .Anchor {
display: flex;
position: relative;
height: 3.5rem;
width: 3.5rem;
padding: 1rem .7rem 1rem 1rem;
opacity: .1;
margin-bottom: 1.7rem;
border-radius: 4rem;
cursor: pointer;
transition: opacity, background-color .7s ease;
z-index: 10;
transition-duration: .44s;
}
.Media-Viewer .Anchor:hover,
.Media-Viewer:active .Modal-User-Interface-Wrapper,
.Media-Viewer-Content:active .Modal-User-Interface-Wrapper {
opacity: .9;
transition-duration: .1s;
transition-delay: 0s;
}
.Media-Viewer .Anchor:hover {
opacity: .7;
background-color:rgba(0, 0, 0, 0.089);
}
/* overlay */
.Media-Viewer::before {
content: '';
position: absolute;
height: 100vh;
width: 100vw;
top: 0;
z-index: 8;
background-color: rgba(0, 0, 0, 0.932);
backdrop-filter: blur(7px);
-webkit-backdrop-filter: blur(10px);
z-index: -1;
}
.Information-Box {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: .4rem; right: 0; left: 0;
margin: 0 auto;
height: 2.7rem;
width: calc(3rem + 10vw);
background: rgb(220,148,87);
background: linear-gradient(133deg, rgba(32, 28, 24, 0.719) 0%, rgba(43, 32, 26, 0.582) 100%);
border-radius: .6rem;
z-index: 10;
}
.Information-Box h4 {
position: absolute;
color: #fff;
font-size: .85rem;
font-weight: 700;
text-shadow: 1px 2px 5px rgb(1, 4, 5);
}
Maybe you'll find something useful here..
Related
I have created a dialog that slides out on closing if on mobile view.
Otherwise it just scales backwards.
This component is based on the awesome work from here:
https://web.dev/building-a-dialog-component/#styling-with-open-props
With some tweeks of my own to adapt it to react and my own needs.
This will add scrollbar on html body for a breef second.
This is super annoying and only fix that works is to hide scrollbar on the html-tag.
html {
box-sizing: border-box;
margin: 0px; padding: 0px
&::-webkit-scrollbar {
display: none;
}
scrollbar-width: none;
}
I do not like this at all, are there any better solutions for this?
import { useEffect, useState, useRef } from "react";
import styled, { keyframes } from "styled-components";
import PropTypes from "prop-types";
import { shadow } from "shared/theme";
import { spacingIndex } from "shared/spacing";
const scaleDown = keyframes`
to { transform: scale(.75) }
`;
const slideOutDown = keyframes`
to { transform: translateY(100%) }
`;
const slideInUp = keyframes`
from { transform: translateY(100%) }
`;
const Container = styled.dialog`
display: ${({ open }) => (open ? "flex" : "none")};
justify-content: center;
align-items: center;
border-radius: 8px;
border: none;
max-inline-size: min(90vw, 60ch);
max-block-size: min(80vh, 100%);
overflow: hidden;
margin: auto;
padding: ${spacingIndex * 2}px;
inset: 0;
box-shadow: ${shadow.overlay};
transition: opacity 0.5s cubic-bezier(0.25, 0, 0.3, 1);
animation: ${scaleDown} 0.5s cubic-bezier(0.25, 0, 0.3, 1) forwards;
animation-timing-function: cubic-bezier(0.5, -0.5, 0.1, 1.5);
&:is([open]) {
animation: ${slideInUp} 0.5s cubic-bezier(0.25, 0, 0.3, 1) forwards;
}
&:not([open]) {
pointer-events: none;
opacity: 0;
}
::backdrop {
backdrop-filter: blur(4px);
transition: backdrop-filter 0.5s ease;
}
#media (max-width: 768px) {
animation: ${slideOutDown} 0.5s cubic-bezier(0.25, 0, 0.3, 1) forwards;
margin-block-end: 16px;
}
`;
const Dialog = ({ isOpened, onClose, children }) => {
const ref = useRef(null);
const [open, setOpen] = useState(false);
const isClickOutsideOfDialog = (dialogEl, event) => {
if (!dialogEl) return false;
const rect = dialogEl.getBoundingClientRect();
return (
event.clientY < rect.top ||
event.clientY > rect.bottom ||
event.clientX < rect.left ||
event.clientX > rect.right
);
};
const onDialogContainerClick = (event) => {
if (isClickOutsideOfDialog(ref.current, event)) onClose();
};
const handleAnimationEnd = (e) => {
if (slideInUp.name !== e.animationName) setOpen(false);
};
useEffect(() => {
ref.current?.addEventListener("animationend", handleAnimationEnd);
return () => ref.current?.removeEventListener("animationend", handleAnimationEnd);
}, []);
useEffect(() => {
if (!isOpened) ref.current?.close();
if (isOpened) {
setOpen(true);
ref.current?.showModal();
}
}, [isOpened]);
return (
<Container
{...{
ref,
open,
onClick: onDialogContainerClick,
}}>
{children}
</Container>
);
};
Dialog.propTypes = {
isOpened: PropTypes.bool,
onClose: PropTypes.func,
};
export default Dialog;
Edit: Guess I was tired and stupid..Just added position:fixed; because I then move the dialog out of the document flow.
the code: https://codesandbox.io/s/goofy-boyd-xscgd
live demo: https://xscgd.csb.app/
I have a nav bar on the page which will show up when you are scrolling up on the page.
The component's code is
import React, { Component } from "react";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import AnchorLink from "react-anchor-link-smooth-scroll";
import { navLinks, navHeight } from "./config";
import Menu from "./Menu";
import styled from "styled-components";
import theme from "../styles/theme";
import media from "../styles/media";
import mixins from "../styles/mixins";
const { colors, fontSizes, fonts } = theme;
const throttle = (func, wait = 100) => {
let timer = null;
return function(...args) {
if (timer === null) {
timer = setTimeout(() => {
func.apply(this, args);
timer = null;
}, wait);
}
};
};
const NavContainer = styled.header`
${mixins.flexBetween};
position: fixed;
top: 0;
padding: 0px 50px;
background-color: ${colors.navy};
transition: ${theme.transition};
z-index: 11;
filter: none !important;
pointer-events: auto !important;
user-select: auto !important;
width: 100%;
height: ${props =>
props.scrollDirection === "none" ? theme.navHeight : theme.navScrollHeight};
box-shadow: ${props =>
props.scrollDirection === "up"
? `0 10px 30px -10px ${colors.shadowNavy}`
: "none"};
transform: translateY(
${props =>
props.scrollDirection === "down" ? `-${theme.navScrollHeight}` : "0px"}
);
${media.desktop`padding: 0 40px;`};
${media.tablet`padding: 0 25px;`};
`;
const Navbar = styled.nav`
${mixins.flexBetween};
position: relative;
width: 100%;
color: ${colors.lightestSlate};
font-family: ${fonts.SFMono};
counter-reset: item 0;
z-index: 12;
`;
const Logo = styled.div`
${mixins.flexCenter};
`;
const LogoLink = styled.a`
display: block;
color: ${colors.green};
width: 42px;
height: 42px;
&:hover,
&:focus {
svg {
fill: ${colors.transGreen};
}
}
svg {
fill: none;
transition: ${theme.transition};
user-select: none;
}
`;
const Hamburger = styled.div`
${mixins.flexCenter};
overflow: visible;
margin: 0 -12px 0 0;
padding: 15px;
cursor: pointer;
transition-timing-function: linear;
transition-duration: 0.15s;
transition-property: opacity, filter;
text-transform: none;
color: inherit;
border: 0;
background-color: transparent;
display: none;
${media.tablet`display: flex;`};
`;
const HamburgerBox = styled.div`
position: relative;
display: inline-block;
width: ${theme.hamburgerWidth}px;
height: 24px;
`;
const HamburgerInner = styled.div`
background-color: ${colors.green};
position: absolute;
width: ${theme.hamburgerWidth}px;
height: 2px;
border-radius: ${theme.borderRadius};
top: 50%;
left: 0;
right: 0;
transition-duration: 0.22s;
transition-property: transform;
transition-delay: ${props => (props.menuOpen ? `0.12s` : `0s`)};
transform: rotate(${props => (props.menuOpen ? `225deg` : `0deg`)});
transition-timing-function: cubic-bezier(
${props =>
props.menuOpen ? `0.215, 0.61, 0.355, 1` : `0.55, 0.055, 0.675, 0.19`}
);
&:before,
&:after {
content: "";
display: block;
background-color: ${colors.green};
position: absolute;
left: auto;
right: 0;
width: ${theme.hamburgerWidth}px;
height: 2px;
transition-timing-function: ease;
transition-duration: 0.15s;
transition-property: transform;
border-radius: 4px;
}
&:before {
width: ${props => (props.menuOpen ? `100%` : `120%`)};
top: ${props => (props.menuOpen ? `0` : `-10px`)};
opacity: ${props => (props.menuOpen ? 0 : 1)};
transition: ${props =>
props.menuOpen ? theme.hamBeforeActive : theme.hamBefore};
}
&:after {
width: ${props => (props.menuOpen ? `100%` : `80%`)};
bottom: ${props => (props.menuOpen ? `0` : `-10px`)};
transform: rotate(${props => (props.menuOpen ? `-90deg` : `0`)});
transition: ${props =>
props.menuOpen ? theme.hamAfterActive : theme.hamAfter};
}
`;
const NavLinks = styled.div`
display: flex;
align-items: center;
${media.tablet`display: none;`};
`;
const NavList = styled.ol`
div {
${mixins.flexBetween};
}
`;
const NavListItem = styled.li`
margin: 0 10px;
position: relative;
font-size: ${fontSizes.smallish};
counter-increment: item 1;
&:before {
content: "0" counter(item) ".";
text-align: right;
color: ${colors.green};
font-size: ${fontSizes.xsmall};
}
`;
const NavLink = styled(AnchorLink)`
padding: 12px 10px;
`;
const ResumeLink = styled.a`
${mixins.smallButton};
margin-left: 10px;
font-size: ${fontSizes.smallish};
`;
const DELTA = 5;
class Nav extends Component {
state = {
isMounted: false,
menuOpen: false,
scrollDirection: "none",
lastScrollTop: 0
};
componentDidMount() {
setTimeout(() => this.setState({ isMounted: true }), 100);
window.addEventListener("scroll", () => throttle(this.handleScroll()));
window.addEventListener("resize", () => throttle(this.handleResize()));
window.addEventListener("keydown", e => this.handleKeydown(e));
}
componentWillUnmount() {
this.setState({ isMounted: false });
window.removeEventListener("scroll", () => this.handleScroll());
window.removeEventListener("resize", () => this.handleResize());
window.removeEventListener("keydown", e => this.handleKeydown(e));
}
toggleMenu = () => this.setState({ menuOpen: !this.state.menuOpen });
handleScroll = () => {
const { isMounted, menuOpen, scrollDirection, lastScrollTop } = this.state;
const fromTop = window.scrollY;
// Make sure they scroll more than DELTA
if (!isMounted || Math.abs(lastScrollTop - fromTop) <= DELTA || menuOpen) {
return;
}
if (fromTop < DELTA) {
this.setState({ scrollDirection: "none" });
} else if (fromTop > lastScrollTop && fromTop > navHeight) {
if (scrollDirection !== "down") {
this.setState({ scrollDirection: "down" });
}
} else if (fromTop + window.innerHeight < document.body.scrollHeight) {
if (scrollDirection !== "up") {
this.setState({ scrollDirection: "up" });
}
}
this.setState({ lastScrollTop: fromTop });
};
handleResize = () => {
if (window.innerWidth > 768 && this.state.menuOpen) {
this.toggleMenu();
}
};
handleKeydown = e => {
if (!this.state.menuOpen) {
return;
}
if (e.which === 27 || e.key === "Escape") {
this.toggleMenu();
}
};
render() {
const { isMounted, menuOpen, scrollDirection } = this.state;
return (
<NavContainer scrollDirection={scrollDirection}>
<Navbar>
<TransitionGroup>
{isMounted && (
<CSSTransition classNames="fade" timeout={3000}>
<Hamburger onClick={this.toggleMenu}>
<HamburgerBox>
<HamburgerInner menuOpen={menuOpen} />
</HamburgerBox>
</Hamburger>
</CSSTransition>
)}
</TransitionGroup>
<NavLinks>
<NavList>
<TransitionGroup>
{isMounted &&
navLinks &&
navLinks.map(({ url, name }, i) => (
<CSSTransition key={i} classNames="fadedown" timeout={3000}>
<NavListItem
key={i}
style={{ transitionDelay: `${i * 100}ms` }}
>
<NavLink href={url}>{name}</NavLink>
</NavListItem>
</CSSTransition>
))}
</TransitionGroup>
</NavList>
<TransitionGroup>
{isMounted && (
<CSSTransition classNames="fadedown" timeout={3000}>
<div style={{ transitionDelay: `600ms` }}>
<ResumeLink
href="/resume.pdf"
target="_blank"
rel="nofollow noopener noreferrer"
>
Resume
</ResumeLink>
</div>
</CSSTransition>
)}
</TransitionGroup>
</NavLinks>
</Navbar>
<Menu menuOpen={menuOpen} toggleMenu={this.toggleMenu} />
</NavContainer>
);
}
}
export default Nav;
The problem is really simple though.
As you can see, when viewing the page through mobile devices, there will be a thick nav bar sticking at the top. I really want to make it thinner(or shorter) and also make its background to transparent. However I tried to find where I should change the code but I couldn't. I am not really good at CSS and hope someone could point out the part of the code I should change to fix this problem.
Note that I only want to change the nav bar for mobile devices.
you need to add breakpoint on your styled NavContainer like this:
const NavContainer = styled.header`
${mixins.flexBetween};
position: fixed;
top: 0;
padding: 0px 50px;
background-color: ${colors.navy};
transition: ${theme.transition};
z-index: 11;
filter: none !important;
pointer-events: auto !important;
user-select: auto !important;
width: 100%;
height: ${props =>
props.scrollDirection === "none" ? theme.navHeight : theme.navScrollHeight};
box-shadow: ${props =>
props.scrollDirection === "up"
? `0 10px 30px -10px ${colors.shadowNavy}`
: "none"};
transform: translateY(
${props =>
props.scrollDirection === "down" ? `-${theme.navScrollHeight}` : "0px"}
);
${media.desktop`padding: 0 40px;`};
${media.tablet`padding: 0 25px;`};
#media (max-width: 768px) {
background-color: rgba(255,255,255,0.5);
height: auto;
}
`;
Seems like you're looking for Media Queries.
They don't appear to be supported with ReactJS in the way you're making variables to store your styles but there is a library that lets you use media queries.
See - https://github.com/ReactTraining/react-media
For more information on media queries in general see - https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries
Essentially you look at the width of the device and then specify a style based on that. Super useful for determining if a client is using a mobile device or not.
You can setup a media query to check for a width < 600px and then based on that change the navbar to be transparent and thinner.
Hope the above helps!
I am having a mysterious problem that did not exist yesterday (you know those?). For some reason, these grey boxes are appearing at the edges of an element that appears when a user hovers over its parent element. they appear to the right and bottom. Essentially, everything below the check and x images is a div with a class of .bottom. I have set to 50% of parent height and 100% of its width. These are react components, so it may be a tad hard to follow. The EventDetail component is nested in the Event component.
.eventcontainer {
padding: 5px;
width: 960px;
margin: 20px auto;
}
.event {
margin-top: 2%;
width: 960px;
border-color:#496DD9;
border-style: dotted;
font-size: 0.5em;
height: 300px;
position: relative;
-webkit-transition: height 300ms ease-out;
}
.event:hover {
height: 400px;
-webkit-transition: height 300ms ease-in;
}
.event:hover .hidden {
display: block;
opacity: 1;
-webkit-transition: opacity 300ms ease-in 200ms;
}
.hidden {
opacity: 0;
overflow: scroll;
-webkit-transition: opacity 100ms ease-out;
}
.bottom {
position: absolute;
bottom: 0;
padding-bottom: 2%;
padding-left: 2%;
font-size: 13px;
width: 100%;
height: 50%;
}
const EventDetail = (props) => {
const options = {
color: '#DE5745',
trailWidth: 1,
strokeWidth: 10,
};
const containerStyle = {
width: '100px',
height: '20px',
};
const showUpdate = (e) => {
e.preventDefault();
props.dispatch(renderUpdate(props.id));
};
return (
<div className=" bottom hidden" >
<p>Attendance</p>
<div className="progressbar">
<Line progress={(props.attending / props.capacity)} containerStyle={containerStyle} initialAnimate options={options} containerClassName={'.progressbar'} />
<span>{props.attending}</span><span>/</span><span> {props.capacity}</span>
</div>
{/* <div>{props.attendeeHelperFunction(props.attendeeList)}</div>*/}
<p>Description:</p>
{props.description === '___' ? <p>The owner did not provide a description. So mysterious</p> : <p>{props.description}</p>}
{window.localStorage.getItem('userid') === props.owner_id ?
<div>
<Update
event_title={props.title}
event_description={props.description}
event_capacity={props.capacity}
event_id={props.event_id}
/>
</div>
: null}
</div>
);
};
const Event = (props) => {
const attendHandler = (e) => {
e.preventDefault();
props.dispatch(attendEvent(props.id))
.then(() => {
props.dispatch(fetchEvents());
});
};
const flakeHandler = (e) => {
e.preventDefault();
props.dispatch(flakeEvent(props.id))
.then(() => {
props.dispatch(fetchEvents());
})
.catch(err => console.log(err));
};
return (
<div className="event">
<section className="eventdescription">
<p>{props.title}</p>
<p>{props.date}</p>
<p>Hosted by: {props.owner}</p>
<p>{console.log('EVENT', renderEvents)}</p>
</section>
<section className="attend"><img onClick={attendHandler}className="eventgraphic" src={check} alt="" /></section>
<section className="unattend"><img onClick={flakeHandler}className="eventgraphic" src={crossout} alt="" /></section>
<EventDetail
title={props.title}
event_id={props.id}
owner_id={props.owner_id}
attending={props.attendees}
capacity={props.capacity}
description={props.description}
attendeeList={props.attendeeList}
attendeeHelperFunction={props.attendeeHelperFunction}
/>
</div>
);
};
They are scrollbars, duh! But if anyone ever stumbles onto this thread, here is a style generator for scroll bars https://mikethedj4.github.io/Webkit-Scrollbar-Generator/
I'm trying to set the keyframes of a pulsate animation in ReactJS. I tried just setting the keyframes inside the inline style but that doesn't work.
My code
const NewRelpyheButton = ({style = {}, open, handleOPenSettings}) => {
var bar = {
color: '#000',
padding: '1em 0',
fontSize: '20px',
textAlign: 'center',
cursor: 'pointer',
position: 'fixed',
bottom: '0',
width: '100%',
zIndex: '10',
animation: 'pulse 1.2s ease-in-out',
animationIterationCount: 'infinite',
}
Object.assign(style, {});
let openModal;
if (open) {
openModal = <Modal><NewRelpyhe/></Modal>
}
return (
<div>
{openModal}
<Bar color='purple' style={bar} onClick={handleOpenSettings}>
create a new relphye site
</Bar></div>
)
}
I'm trying to mimic this in css:
.element {
width: 100%;
height: 100%;
animation: pulse 5s infinite;
}
#keyframes pulse {
0% {
background-color: #001F3F;
}
100% {
background-color: #FF4136;
}
}
html,
body {
height: 100%;
}
If you like to keep all your styling tightly coupled to your components, give Styled Components a go. They have a helper for keyframes
e.g.
import styled, { keyframes } from 'styled-components'
const pulse = keyframes`
from {
background-color: #001F3F;
}
to {
background-color: #FF4136;
}
`
const Bar = styled.div`
color: #000;
padding: 1em 0;
font-size: 20px,
text-align: center;
cursor: pointer;
position: fixed;
bottom: '0',
width: 100%;
z-index: 10;
animation: ${pulse} 1.2s ease-in-out;
animation-iteration-count: infinite;
`
Then use like so:
<Bar>I pulse</Bar>
Here's how we will achieve it without adding any dependency.
{/*Your Js File Code */}
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import React from "react";
import "./test.css";
class Anim extends React.Component {
constructor(props) {
super(props);
this.state = {
animationName: ""
};
}
addStylesheetRules(rules) {
var styleEl = document.createElement("style");
document.head.appendChild(styleEl);
var styleSheet = styleEl.sheet;
styleSheet.insertRule(rules, 0);
}
clickHdl() {
let animationName = `animation${Math.round(Math.random() * 100)}`;
let keyframes = `
#-webkit-keyframes ${animationName} {
10% {-webkit-transform:translate(${Math.random() * 300}px, ${
Math.random() * 300
}px)}
90% {-webkit-transform:translate(${Math.random() * 300}px, ${
Math.random() * 300
}px)}
100% {-webkit-transform:translate(${Math.random() * 300}px, ${
Math.random() * 300
}px)}
}`;
this.addStylesheetRules(keyframes);
this.setState({
animationName: animationName
});
}
render() {
let style = {
animationName: this.state.animationName,
animationTimingFunction: "ease-in-out",
animationDuration: "0.6s",
animationDelay: "0.0s",
animationIterationCount: 1,
animationDirection: "normal",
animationFillMode: "forwards"
};
return (
<div>
<button type="button" onClick={this.clickHdl.bind(this)}>
Animation!
</button>
<div className="box" style={style}></div>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<StrictMode>
<Anim />
</StrictMode>,
rootElement
);
{/*Css Code test.css */}
.box {
width: 30px;
height: 30px;
background: red;
border-radius: 50%;
cursor: pointer;
}
Demo: https://codesandbox.io/s/reverent-sun-qjo91?file=/src/index.js
I have finished a webpage I am working on, but unfortunately, I've only designed it for a 1920x1080 monitor. Whenever the site is viewed on other window sizes/monitor resolutions, the page does not adjust properly. Could someone possibly fix this so that the page is scaled accordingly when the window size is changed or it is viewed on mobile? If anyone could fix the code so that it would adjust to any browser side, that would be great. I've been working on it for a while. Here's the entire page:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Vortex Network</title>
</head>
<link href='https://fonts.googleapis.com/css?family=Luckiest+Guy' rel='stylesheet' type='text/css'>
<script>
window.onresize = function(event) {
...
}
</script>
<script>
(function(){
/**
author: #manufosela
2013/08/27 copyleft 2013
ShootingStar class Main Methods:
launch: launch shooting stars every N seconds received by param. 10 seconds by default.
launchStar: launch a shooting star. Received options object by param with:
- dir (direction between 0 and 1)
- life (between 100 and 400)
- beamSize (between 400 and 700)
- velocity (between 2 and 10)
**/
ShootingStar = function( id ) {
this.n = 0;
this.m = 0;
this.defaultOptions = { velocity:8, starSize:10, life:300, beamSize:400, dir:-1 };
this.options = {};
id = ( typeof id != "undefined" )?id:"";
this.capa = ( $( id ).lenght > 0 )?"body":id;
this.wW = $( this.capa ).innerWidth();
this.hW = $( this.capa ).innerHeight();
};
ShootingStar.prototype.addBeamPart = function( x, y ) {
this.n++;
var name = this.getRandom( 100, 1 );
$( "#star"+name ).remove();
$( this.capa ).append( "<div id='star"+name+"'></div>" );
$( "#star"+name ).append( "<div id='haz"+this.n+"' class='haz' style='position:absolute; color:#FF0; width:10px; height:10px; font-weight:bold; font-size:"+this.options.starSize+"px'>·</div>" );
if ( this.n > 1 ) $( "#haz" + ( this.n - 1 ) ).css( { color:"rgba(255,255,255,0.5)" } );
$( "#haz" + this.n ).css( { top: y + this.n, left: x + ( this.n * this.options.dir ) } );
}
ShootingStar.prototype.delTrozoHaz = function() {
this.m++;
$( "#haz" + this.m ).animate( {opacity:0}, 75 );
if ( this.m >= this.options.beamSize ) { $( "#ShootingStarParams" ).fadeOut( "slow" ); }
}
ShootingStar.prototype.getRandom = function( max, min ) {
return Math.floor( Math.random() * (max - min + 1)) + min;
}
ShootingStar.prototype.toType = function ( obj ) {
if ( typeof obj === "undefined" ) { return "undefined"; /* consider: typeof null === object */ }
if ( obj === null ) { return "null"; }
var type = Object.prototype.toString.call( obj ).match( /^\[object\s(.*)\]$/ )[1] || '';
switch ( type ) {
case 'Number': if ( isNaN( obj ) ) { return "nan"; } else { return "number"; }
case 'String': case 'Boolean': case 'Array': case 'Date': case 'RegExp': case 'Function': return type.toLowerCase();
}
if ( typeof obj === "object" ) { return "object"; }
return undefined;
}
ShootingStar.prototype.launchStar = function( options ) {
if ( this.toType( options ) != "object" ) { options = {}; }
this.options = $.extend( {}, this.defaultOptions, options );
this.n=0;
this.m=0;
var i=0, l=this.options.beamSize,
x=this.getRandom( this.wW - this.options.beamSize - 100, 100 ), y=this.getRandom( this.hW - this.options.beamSize - 100, 100 ),
self = this;
for( ; i<l; i++ ) { setTimeout( function(){ self.addBeamPart( x, y ); }, self.options.life + ( i * self.options.velocity ) ); }
for( i=0; i<l; i++ ) { setTimeout( function(){ self.delTrozoHaz() }, self.options.beamSize + ( i * self.options.velocity ) ); }
$( "#ShootingStarParams" ).html();
$( "#ShootingStarParams" ).fadeIn( "slow" );
}
ShootingStar.prototype.launch = function( everyTime ) {
if ( this.toType( everyTime ) != "number" ) { everyTime = 2; }
everyTime = everyTime * 1000;
this.launchStar();
var self = this;
setInterval( function() {
var options = {
dir: ( self.getRandom( 1, 0 ))?1:-1,
life: self.getRandom( 400, 100 ),
beamSize: self.getRandom( 700, 400 ),
velocity: self.getRandom( 10, 4 )
}
self.launchStar( options );
}, everyTime );
}
})();
</script>
</div>
<style type="text/css">
#top-image {
background:url('https://www.14denoviembre.es/img/stars_5.png') -25px -50px;
position:fixed ;
top:0;
width:100%;
height:100%;
background-size: calc(100% + 50px);
z-index:98;
}
body {
color:#FFF;
height:55%;
width:100%;
height:100%;
color:#FFF;
min-width:100%;
width: auto !important;
}
.stars {
position: absolute;
background-image: url( http://www.14denoviembre.es/img/hori.png ), url( http://www.14denoviembre.es/img/stars_5.png );
background-repeat: repeat-x,repeat-x repeat-y;
transform:translate3D(0em, 0em, 0);
animation: stars 21s ease;
transform-style: preserve-3d;
}
.Icon {
width: 100%;
height: 19%;
top: 5px;
position: fixed;
padding: 10px;
display: block;
margin:auto;
align-content: center;
}
.container {
position: relative;
top: 0px;
text-align: center;
}
#logo {
height:auto;
}
.shadowfilter {
-webkit-filter: drop-shadow(0px 0px 0px rgba(0,0,0,0.80));
-webkit-transition: all 0.5s linear;
-o-transition: all 0.5s linear;
transition: all 0.5s linear;
}
.shadowfilter:hover {
-webkit-filter: drop-shadow(0px 0px 8px rgba(255, 255, 179, 0.8));
}
#thumbs {
position: relative;
width: 52%;
margin-top: 30%;
margin-left: auto;
margin-right: auto;
z-index: 10000;
text-align: justify;
-ms-text-justify: distribute-all-lines;
text-justify: distribute-all-lines;
}
.status {
position: relative;
height: 5%;
margin: auto;
width: 27%;
border: 3px solid #ffffff;
text-align: center;
-moz-box-shadow: inset 0 0 75px #ffffff;
-webkit-box-shadow: inset 0 0 75px #ffffff;
box-shadow: inset 0 0 75px #ffffff;
z-index:99;
}
.stretch {
width: 100%;
display: inline-block;
font-size: 5;
}
.floating{
float: left;
-webkit-animation-name: Floatingx;
-webkit-animation-duration: 3s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: ease-in-out;
-moz-animation-name: Floating;
-moz-animation-duration: 3s;
-moz-animation-iteration-count: infinite;
-moz-animation-timing-function: ease-in-out;
margin-left: 30px;
margin-top: 5px;
}
#-webkit-keyframes Floatingx{
from {-webkit-transform:translate(0, 0px);}
65% {-webkit-transform:translate(0, 15px);}
to {-webkit-transform: translate(0, -0px); }
}
#-moz-keyframes Floating{
from {-moz-transform:translate(0, 0px);}
65% {-moz-transform:translate(0, 15px);}
to {-moz-transform: translate(0, -0px);}
}
.scaling{
float: center;
-webkit-animation-name: scalex;
-webkit-animation-duration:3s;
-webkit-animation-iteration-count:infinite;
-webkit-animation-timing-function:ease-in-out;
-moz-animation-name: scale;
-moz-animation-duration:3s;
-moz-animation-iteration-count:infinite;
-moz-animation-timing-function:ease-in-out;
}
#-webkit-keyframes scalex{
from {-webkit-transform: scale(0.9);}
65% {-webkit-transform: scale(1.0);}
to {-webkit-transform: scale(0.9);}
}
#-moz-keyframes scale{
from {-moz-transform: scale(0.9);}
65% {-moz-transform: scale(1.0);}
to {-moz-transform: scale(0.9);}
}
.zoom_img img{
-moz-transition:-moz-transform 0.2s ease-in;
-webkit-transition:-webkit-transform 0.2s ease-in;
-o-transition:-o-transform 0.2s ease-in;
}
.zoom_img img:hover{
-moz-transform:scale(1.1);
-webkit-transform:scale(1.1);
-o-transform:scale(1.1);
}
p {
font-family: 'Luckiest Guy', cursive;
-webkit-text-stroke: 3px black;
color: #ae00de;
font-size: 2.6em;
margin:0px;
}
</style>
<body class="stars">
<div class="zoom_img">
<div id="thumbs">
<img class="shadowfilter" src="http://s15.postimg.org/i03eeyw23/Forums_After.png" alt="Forums_Icon"/>
<img class="shadowfilter" src="http://s15.postimg.org/vshtalmtn/Vote_After.png" alt="Vote_Icon"/>
<img class="shadowfilter" src="http://s15.postimg.org/j4xgkciiz/Store_After.png" alt="Shop_Icon" height="200" width="190"/>
<img class="shadowfilter" src="http://s15.postimg.org/ds8m67umj/Staff_After_2.png" alt="Staff_Icon" height="200" width="200"/>
<img class="shadowfilter" src="http://s15.postimg.org/5vo4xzj63/Bans_After_2.png" alt="Bans_Icon"/>
<span class="stretch"></span>
</div>
</div>
<div class="container">
<div class="Icon">
<img src="http://files.enjin.com/353719/module_header/10950667/background/Vortex-Network-Logonew.png" class="scaling" width="642" height="460"></img>
</div>
</div>
<div class="status">
<p>play.vortexpvp.com</p>
</div>
<div id="top-image"></div>
<div id="ShootingStarParams"></div>
<script type="text/javascript" src="http://codeorigin.jquery.com/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="ShootingStarClass.js"></script>
<script type="text/javascript">
$( document ).ready( function(){
var shootingStarObj = new ShootingStar( "body" );
shootingStarObj.launch();
});
</script>
</div>
</body>
</html>
Thanks in advance for any help!
Use CSS3 #media Rule
you should apply CSS3 #media Rule to all the elements included in your website,
for example you have a #top-image style css:
#top-image {
background:url('https://www.14denoviembre.es/img/stars_5.png') -25px -50px;
position:fixed ;
top:0;
width:100%;
height:100%;
background-size: calc(100% + 50px);
z-index:98;
}
#media screen and (min-width: 480px) {
#top-image {
width:20%;
height:20%;
}
}
it will alter the #top-image's max width and height if the viewport is 480 pixels wide or wider.
Learn the syntax before you apply it to your website: http://www.w3schools.com/cssref/css3_pr_mediaquery.asp