I am building a simple push-down effect which affects the position of two containers. So far I have managed to achieve a near-desired effect using fixed positioning for the hidden container while changing its position to a relative for the opened state.
I want to apply a smooth transition to the blue main div, which is being pushed down by the hidden div with a class of .sub-header. How can I bypass the choppy rearrangement of the containers and is there a more elegant way of doing this instead of switching positioning on click? (e.g. fixed to a relative in this case)
Currently, when I switch the positioning from fixed to a relative as expected - there is a gap being produced, which is the .sub-header's height.
NOTE: The heights of the current divs are fixed values, but I need this to be able to handle dynamic changes in the .sub-header height.
NOTE: This should be achieved by adding a custom class, not using jQuery's nested effects like .slideToggle etc.
Here is the Fiddle.
And the simple jQuery function needed for the Fiddle share:
$('.trigger').click(function() {
$('.sub-header').toggleClass('opened');
}).stop();
Make position: relative; and do margin top for animating
$('.trigger').click(function() {
$('.sub-header').toggleClass('opened');
}).stop();
body {
font-family: 'Helvetica Neue', 'Helvetica', Arial, sans-serif;
margin: 0;
padding: 0;
box-sizing: border-box;
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
}
header,
.sub-header,
main {
display: flex;
justify-content: center;
align-items: center;
align-content: center;
flex-direction: column;
font-weight: bold;
text-transform: uppercase;
color: #fff;
transition: all .5s ease-in-out;
}
header {
height: 100px;
background: tomato;
z-index: 1000;
position: relative;
}
.sub-header {
height: 150px;
background: gainsboro;/*
transform: translateY(-200%);*/
margin-top:-150px;
left: 0;
right: 0;
z-index: 10;
position: relative;
}
.opened {/*
transform: translateY(0%);*/
margin-top:0;
}
main {
height: 250px;
background: deepskyblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header>Header content TRIGGER</header>
<div class="sub-header">Sub Header content</div>
<main>Main Content</main>
Update:-
As to get -100% you have make it float and set all width to 100%
$('.trigger').click(function() {
$('.sub-header').toggleClass('opened');
}).stop();
body {
font-family: 'Helvetica Neue', 'Helvetica', Arial, sans-serif;
margin: 0;
padding: 0;
box-sizing: border-box;
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
}
header,
.sub-header,
main {
display: flex;
justify-content: center;
align-items: center;
align-content: center;
flex-direction: column;
font-weight: bold;
text-transform: uppercase;
color: #fff;
transition: all .5s ease-in-out;
}
header {
width:100%;
height: 100px;
background: tomato;
z-index: 1000;
position: relative;
}
.sub-header {
height: 150px;
width:100%;
background: gainsboro;/*
transform: translateY(-200%);*/
margin-top:-100%;
left: 0;
right: 0;
z-index: 10;
float:left;
}
.opened {/*
transform: translateY(0%);*/
margin-top:0;
}
main {
width:100%;
height: 250px;
background: deepskyblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<header>Header content TRIGGER</header>
<div class="sub-header">Sub Header content</div>
<main>Main Content</main>
Correct me if I misunderstood your question, but I guess there's much simpler approach to what you're trying to achieve. Try changing corresponding classes in your CSS code:
.sub-header {
background: gainsboro;
height: 0;
-webkit-transition: height .3s linear;
transition: height .3s linear;
}
.opened {
height: 150px;
}
Here's the fiddle. My approach does not cover all bases, as you can see there is still text visible in the hidden container, which is going to need some additional workaround in your js or css, but I guess it is simpler than yours, considering that your .sub-container has fixed height.
EDIT
For non fixed height, there is workaround in my approach:
.sub-header {
background: gainsboro;
height: auto;
max-height: 0px;
-webkit-transition: max-height .3s linear;
transition: max-height .3s linear;
}
.opened {
max-height: 400px;
}
but it still needs to be adjusted - when you set .opened's max-height to the lower value, transition is going to be slower. It is not perfect, thought it covers cases, where .sub-containers' heights are relatively similar.
please check this out. we can use margin for styling and keep position the same relative
$('.trigger').click(function() {
$('.sub-header').toggleClass('opened');
}).stop();
body {
font-family: 'Helvetica Neue', 'Helvetica', Arial, sans-serif;
margin: 0;
padding: 0;
box-sizing: border-box;
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
}
header,
.sub-header,
main {
display: flex;
justify-content: center;
align-items: center;
align-content: center;
flex-direction: column;
font-weight: bold;
text-transform: uppercase;
color: #fff;
transition: all .5s ease-in-out;
}
header {
height: 100px;
background: tomato;
z-index: 1000;
position: relative;
}
.sub-header {
height: 150px;
background: gainsboro;
transform: translateY(-200%);
left: 0;
right: 0;
z-index: 10;
/*play with position and margin*/
position: relative;
margin-bottom:-200px;
}
.opened {
transform: translateY(0%);
margin-bottom:0;
}
main {
height: 250px;
background: deepskyblue;
}
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<header>Header content TRIGGER</header>
<div class="sub-header">
<p>Sub Header content</p>
</div>
<main>Main Content</main>
Related
I'm looking for a way in CSS (or JS but preferably CSS) to define the breakpoint where text starts to wrap. I'm using React 17/CRA and CSS modules.
I have a React app that has a header bar with two pieces of content. On the left-hand side is the three-word title of the app in an h1 tag. On the right-hand side is the logged-in user's profile photo and name, composed of several elements within a span. If I narrow the viewframe, first the content overflows and then, if I narrow it more, the title of the app starts to wrap.
I would like the title to wrap before any overflow happens so all the content stays on the screen as long as possible. All the Googling I've done has only come up with info on overflow-wrap or word-break, which aren't what I'm looking for. The text is wrapping like I want it to, I'd just rather it did so sooner.
The code of my component is:
import React from 'react'
import anonymousAvatar from './anonymousAvatar.jpg'
import styles from './dashboardHeader.module.css'
const DashboardHeader ({data}) => (
<div className={styles.root}>
<div className={styles.bar}>
<span className={styles.headerContainer}>
<h1 className={styles.header}>Three Word Title</h1>
</span>
<span className={styles.profile}>
<div className={styles.profileText}>
<p className={styles.textTop}>{data.name}</p>
<p className={styles.textBottom}>{data.email}</p>
</div>
<img className={styles.avatar} src={data.image_url || anonymousAvatar} alt='User Avatar' referrerPolicy='no-referrer' />
</span>
</div>
</div>
)
export default DashboardHeader
The CSS module I currently have is:
.root {
position: fixed;
top: 0;
width: 100%;
}
.bar {
width: 100%;
height: 64px;
padding: 12px 16px;
background-color: #000;
color: #fff;
display: flex;
justify-content: space-between;
}
.headerContainer {
display: grid;
align-items: center;
}
.header {
font-family: 'Cinzel Decorative', sans-serif;
margin: 0;
font-size: 1.5rem;
}
.profile {
background-color: #000;
border: none;
display: grid;
align-items: center;
grid-template-columns: 2fr 1fr;
max-width: 30%;
cursor: pointer;
margin-right: 16px;
}
.profileText {
display: grid;
}
.textTop, .textBottom {
font-family: 'Quattrocento Sans', Arial, Helvetica, sans-serif;
font-size: 1.025rem;
color: #fff;
text-align: right;
margin: auto 0;
}
.textTop {
margin-bottom: 2px;
}
.textBottom {
margin-top: 2px;
}
.avatar {
height: 64px;
width: 64px;
border-radius: 50%;
box-shadow: 0px 0px 12px #fff;
margin-left: 24px;
margin-right: 16px;
}
Here is the component at the full width of my laptop screen:
Here it is at an intermediate width:
And here it is at the very narrow width where the text finally starts to wrap (notice there is still overflow):
As noted in the comments you can simply change the width of the element at your desired breakpoint like in the top blue div of the example below. I'm using animations to help you visualize the results but you would decrease the width of the element in question at your media query breakpoint. I recommend this method because it doesn't require you to increase your HTML markup.
body, div, p, span {
display: flex; justify-content: center; align-items: center;
background-color: #eee;
font-family: Arial;
}
div {
justify-content: space-between;
transform: translateY( -5rem );
position: absolute;
width: 90%; height: 5rem;
padding: 1rem;
background-color: #222; color: #eee;
}
div, div:nth-of-type( 1 ) p:first-of-type {
animation-name: contract; animation-duration: 5s;
animation-timing-function: ease-in-out; animation-iteration-count: infinite;
}
div:nth-of-type( 2 ) {
transform: translateY( 5rem );
}
#keyframes contract { 100% { width: 25%; } }
p {
background-color: transparent;
text-transform: uppercase;
}
p:first-of-type {
font-size: 1.5rem; font-weight: bold;
}
span {
margin: 0.5rem;
border-radius: 50%;
width: 2.5rem; height: 2.5rem;
}
<style>
* {
box-sizing: border-box; padding: 0; margin: 0;
}
html, body {
height: 100%;
}
html {
font-size: 0.5rem;
}
div:nth-of-type( 1 ) p:first-of-type::before,
div:nth-of-type( 2 ) p:first-of-type::before {
content: 'wraps first';
position: absolute; top: -4rem;
border-radius: 1rem; padding: 1rem;
background-color: #07f; white-space: nowrap;
}
div:nth-of-type( 2 ) p:first-of-type::before {
content: 'wraps last';
top: auto; bottom: -4rem;
background-color: #f07;
}
</style>
<div>
<p>three word title</p>
<p>name <br> foo#gmail.com<span></span></p>
</div>
<div>
<p>three word title</p>
<p>name <br> foo#gmail.com<span></span></p>
</div>
I'm simply using the contract animation to manually decrease the width of the paragraph in the first div before it's width is forced smaller by its container. If this doesn't work in your particular setup you could use hidden <br> elements with display: none until your desired breakpoint to set them to block.
I have a 3 panel image section (section 1, 2 and 3) - on hover over section 1 for example, I would like for the original bg to fade out while a new bg fades in while simultaneously growing to the full length of the section "overlapping" the other sections. Once this section is full width I would like to be able to hover over section two and the same process occur without having to actually move the mouse out of the section area first.
I have managed to get to a point where the section expands and the image changes over, however, once say section 1 is expanded - it occupies the full width of the section so hovering over section 2 does not trigger the hover animation for section 2. Instead I have to move the mouse so that it is outside of the section and re-enter over section 2 to begin that animation.
Its probably easier to see so attached is a jsfiddle in addition to the code below.
https://jsfiddle.net/tr5km94w/1/
<div class="panel-test-background">
<div class="panel-test-one"></div>
<div class="panel-test-two"></div>
<div class="panel-test-three"></div>
</div>
<div class="panel-container">
<div class="panel-one">
<div class="panel-text-one">
<div class="text-top">
<h3>section</h3>
<br />
<h1>Section Title No.01</h1>
<br />
</div>
</div>
</div>
<div class="panel-two">
<div class="panel-text-two">
<div class="text-top">
<h3>section</h3>
<br />
<h1>Section Title No.02</h1>
</div>
</div>
</div>
<div class="panel-three">
<div class="panel-text-three">
<div class="text-top">
<h3>section</h3>
<br />
<h1>Section Title No.03</h1>
</div>
</div>
</div>
</div>
<style>
.panel-container {
width: 100%;
height: 75vh;
display: flex;
}
.panel-one {
flex-grow: 1;
height: 75vh;
position: relative;
pointer-events: none;
}
.panel-two {
flex-grow: 1;
height: 75vh;
position: relative;
pointer-events: none;
left: 6px;
}
.panel-three {
flex-grow: 1;
height: 75vh;
position: relative;
pointer-events: none;
}
.panel-text-one {
flex-grow: 1;
height: 75vh;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 3rem;
pointer-events: none;
}
.panel-text-two {
flex-grow: 1;
height: 75vh;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 3rem;
pointer-events: none;
}
.panel-text-three {
flex-grow: 1;
height: 75vh;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 3rem;
pointer-events: none;
}
.panel-text-one h3 {
font-family: "Arial", sans-serif;
font-size: 1.5rem;
color: white;
}
.panel-text-one h1 {
font-family: "Arial", sans-serif;
font-size: 2rem;
color: white;
}
.panel-text-one span {
color: white;
}
.panel-text-two h3 {
font-family: "Arial", sans-serif;
font-size: 1.5rem;
color: white;
}
.panel-text-two h1 {
font-family: "Arial", sans-serif;
font-size: 2rem;
color: white;
}
.panel-text-two span {
color: white;
}
.panel-text-three h3 {
font-family: "Arial", sans-serif;
font-size: 1.5rem;
color: white;
}
.panel-text-three h1 {
font-family: "Arial", sans-serif;
font-size: 2rem;
color: white;
}
.panel-text-three span {
color: white;
}
.panel-test-background {
width: 100%;
height: 75vh;
position: absolute;
display: flex;
}
.panel-test-one {
flex-grow: 1;
height: 75vh;
background: red;
width: 0%;
transition: width 0.5s;
}
.panel-test-one:hover {
width: 100%;
transition: width 0.5s;
background: blue;
}
.panel-test-two {
flex-grow: 1;
height: 75vh;
background: green;
width: 0%;
transition: width 0.5s;
}
.panel-test-two:hover {
width: 100%;
transition: width 0.5s;
background: yellow;
}
.panel-test-three {
flex-grow: 1;
height: 75vh;
background: purple;
width: 0%;
transition: width 0.5s;
}
.panel-test-three:hover {
width: 100%;
transition: width 0.5s;
background: pink;
}
</style>
The issue I am having then I guess is that because whichever section you initially hover over takes up the full width of the container so that when section 1 is expanded, although I am hovered over section 2 or 3 it is still technically section 1 since it is full-width. Is there anyway around this so that I can trigger the other animations when I hover over the respective sections? Any help is greatly appreciated.
Thank you
edit: for a bit of clarification of what an ideal end would like look, I was inspired by the image section on basicagency.com near the end of the homepage.
One thing I did notice is that with the initial it appears that there are only 3 's and there should be 4 's before the next section begins. This may be helpful to try.
I have looked through various pages, but have not managed to find a working solution. I want the text in my div to get more transparent gradually when I scroll. Please, can anybody help? Here is my code:
<script src = "/js/titleScroll.js"></script>
<div class = "header-title">
<h1>Title</h1>
</div>
and:
$(document).ready(function() {
$(window).scroll(function() {
if ($(this).scrollTop() > 0) {
$('header-title').css('opacity', 0.8);
} else {
$('header-title').css('opacity', 1);
}
});
});
and here is my css:
.header-title {
width: 80%;
height: 100px;
left: 50%;
top: 50%;
font-size: 1.5em;
text-align: center;
transform: translateX(-50%);
margin-top: -50px;
position: relative;
max-width: 100%;
background-attachment: fixed;
position: float;
}
.header-title h1 {
color: white;
text-shadow: 2px 2px 4px #d1d1d1;
font-family: arial, sans-serif;
white-space: nowrap;
text-transform: uppercase;
display: inline-block;
}
Thank you.
Problem is, currently you are just triggering 0.8 opacity when user is not at top of the page. Try to get top offset each time scroll is executed and then apply opacity based on that offset, it can be linear function, or more complex ones - it's up to you how it's gonna fade in/out.
Here's very quick working example:
<head>
<style>
body {
min-height: 4000px;
}
.header-title {
position: fixed;
width: 80%;
height: 100px;
left: 50%;
top: 50%;
font-size: 1.5em;
text-align: center;
transform: translateX(-50%);
margin-top: -50px;
max-width: 100%;
background-attachment: fixed;
}
.header-title h1 {
color: white;
text-shadow: 2px 2px 4px #d1d1d1;
font-family: arial, sans-serif;
white-space: nowrap;
text-transform: uppercase;
display: inline-block;
}
</style>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
</head>
<body>
<script>
$(document).ready(function() {
$(window).scroll(function(event) {
let scroll = $(this).scrollTop();
let opacity = 1 - (scroll / 1000);
if (opacity >= 0) {
$('.header-title').css('opacity', opacity);
}
});
});
</script>
<div class = "header-title">
<h1>Title</h1>
</div>
</body>
https://jsfiddle.net/un2bdvfm/
I have a simple leaflet map with a GeoJSON point layer.
I want an infobox instead of the regular pop-up, so, in HTML, I have created the following:
<div id="panoutitlu" class="info-container" style="z-index: 601">
<div class="info-title">
<h1>Selectați ceva</h1>
</div>
<div class="info-body" id="corp">
<div class="info-content-container">
<div class="info-content" id="panoutext"></div>
</div>
</div>
</div>
When clicking on one of the points in the layer, the div named info-title gets populated with an attribute from the GeoJSON, as follows:
function onEachFeature(feature, layer) {
layer.on({
click: function populate() {
document.getElementById('panoutitlu').innerHTML = feature.properties.adresa;
});
The thing I can't get to work is how to expand the div when the info-title is clicked, similar to this map. I want to recreate the exact behaviour, including the smooth transition. That's why I took the CSS from it and changed a few sizes and fonts:
.info-title {
height: 80px;
font-family: 'Fira Sans Condensed';
font-size: 30px;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
user-select: none;
color: #FFF;
position: fixed;
top: 0;
left: 0;
width: 100%;
}
.info-content {
padding: 0 8% 24px 8%;
margin: 0 auto;
background: #385c54;
overflow-y: scroll;
font-family: 'Fira Sans Condensed';
font-size: 1rem;
line-height: 1.25em;
font-weight: 300;
}
.info-container {
position: absolute;
overflow-y: hidden;
bottom: 0;
right: 250px;
z-index: 1000;
background: #385c54;
cursor: pointer;
width: 300px;
height: 60vh;
color: #FFF;
font-family: 'Fira Sans Condensed';
font-size: 18px;
transition: all 0.4s ease-in-out;
transform: translateY(calc(100% - 80px));
}
.info-container.info-active {
transform: translateY(0);
}
.info-body {
margin-top: 80px;
overflow-y: scroll;
overflow-x: hidden;
position: relative;
height: 80%;
}
In JavaScript, I tried adding an event listener:
document.getElementById('panoutitlu').addEventListener("click", toggle('info-active') );
but it didn't work.
Hopefully, somebody can help.
The solution was indeed an Event Listener:
document.getElementById('panoutitlu').addEventListener("click", function slide() {this.classList.toggle('info-active');}
I have some nested elements, one of which is an image that scales when you hover over the container. The problem is that the image jumps slightly before it scales. I know it has to do with the extra content inside the container, but I can't figure out why or what to do about it.
I'd also like the scale transformation to reverse smoothly when you stop hovering over the container.
Here is the site: http://totisdev.azurewebsites.net/productos/
Relevant HTML
<div class="slide">
<div class="slide__content">
<img />
<div class="slide__text_hover">
<h2>Totis</h2>
</div>
<div class="slide__text">
<span>3 Productos</span>
<h2><span>Totis</span></h2>
<span>ver más </span><img />
</div>
</div>
</div>
Possibly relevant SASS
.slide {
display: inline-block;
vertical-align: top;
padding-top: 50px;
.slide__content {
position: relative;
max-height: 350px;
> img {
max-height: 300px;
width: auto;
margin-bottom: -50px;
margin-left: -72px;
display: inline-block;
}
}
.slide__text {
position: relative;
text-align: left;
max-width: 220px;
h2 {
box-sizing: content-box;
font-size: 40px;
max-width: 280px;
white-space: normal;
}
img {
vertical-align: middle;
display: inline-block;
}
}
&:hover .slide__content > img {
-webkit-transform: scale(1.08);
transform: scale(1.08);
-webkit-transition: 0.6s ease;
transition: 0.6s ease;
}
.slide__text_hover {
display: none;
vertical-align: top;
position: relative;
top: -25px;
height: 300px;
padding: 25px 25px 25px 150px;
z-index: -1;
left: -200px;
h2 {
visibility: hidden;
font-size: 60px;
max-width: 280px;
white-space: normal;
box-sizing: content-box;
}
}
&:hover .slide__text_hover {
display: inline-block;
vertical-align: top;
}
&:hover .slide__text {
position: relative;
top: -170px;
transform: translateY(-50%);
transition: transform 0.6s ease;
z-index: 2;
margin-left: 200px;
h2 {
font-size: 60px;
max-width: 280px;
}
a {
display: inline-block;
}
}
}
note: I'm currently transitioning the opacity with javascript, but it shouldn't matter.
Any and all help / feedback appreciated. Thanks!
It's because you're moving other elements around while the scale is happening. For a simple proof-of-concept try adding display:none to .slide__text_hover and .slide__text - you'll see that the elements scale up without jumping.
It's up to you how to handle this and how you position these elements because I'm assuming that display:none isn't a real solution 😉 You could move the elements around, preallocate the space for these elements, add more code so that the other elements slide over smoothly (transform:translateX) as a few suggestions. This is starting to get into the 'too broad' stackoverflow no-man's-land, though.