Make div with position absolute scrolleable - javascript

I'm trying to make a chat HTML template. But I'm having some problems to make scrolleable the messages area.
My structure is like this:
Chat header: to the top with the title of the chat or name person.
Chat input message: to the bottom you can write.
Chat visible area: total height - (chat header height + chat input message height).
Messages: Must increment it height but always be at the bottom of the chat visible area, to read the last message.
All this structure lives with other html elements, is not fullscreen.
My HTML structure is like this:
<div id="chat-1" class="chat-ventana">
<div class="chat-header">
<h4>Header</h4>
</div>
<div class="chat-mensajes-contenedor">
<div class="chat-mensajes-contenedor-general">
<div class="mensaje-contenedor">
<!-- messages content -->
</div>
</div>
</div>
<div class="chat-textarea">
<textarea class="form-control" placeholder="Type your message"></textarea>
</div>
</div>
And my CSS looks is this:
.chat-container {
height: 70vh;
min-height: 400px;
}
.chat-ventana {
position: relative;
display: inline-block;
width: 65%;
float: left;
}
.chat-ventana, .chat-mensajes-contenedor {
height: 100%;
}
.chat-mensajes-contenedor, .chat-mensajes-contenedor-general {
padding: 15px 15px 20px 15px;
}
.chat-header {
z-index: 1;
position: absolute;
top: 0;
left: 0;
width: 100%;
}
.chat-mensajes-contenedor {
position: relative;
overflow-x: hidden;
overflow-y: scroll;
height: 400px;
}
.chat-mensajes-contenedor-general {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
}
.chat-ventana, .chat-mensajes-contenedor {
height: 100%;
}
.chat-mensajes-contenedor {
height: calc(100% - 46px);
}
.chat-mensajes-contenedor, .chat-mensajes-contenedor-general {
padding: 66px 20px 25px 20px;
}
.chat-textarea {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
}
.chat-textarea .form-control {
resize: none;
height: 46px;
padding: 10px 20px;
}
I see if I set .chat-mensajes-contenedor-general to position: relative; it becomes scrolleable but I can't position it to the bottom.

I think I get what you're after.
And it's probably obvious but since you didn't say we can't use javascript you can of course employ a little of it (using jQuery in the case below) to achieve the same end result:
[JSFIDDLE]
function returnScrollHeight() {
return this.scrollHeight;
}
$('.chat-mensajes-contenedor').scrollTop(returnScrollHeight);
$('textarea.form-control').on('keyup', function (e) {
if (e.ctrlKey && e.keyCode === 13) {
$('.mensaje-contenedor').append('<div class="line">' + this.value + '</div>');
$('.chat-mensajes-contenedor').scrollTop(returnScrollHeight);
this.value = '';
}
});
I couldn't come up with a non-js solution in the brief time I tried. Hopefully someone else will come along and give the pure html/css answer.

Here is a fiddle: https://jsfiddle.net/gLahjk5z/3/
I changed the position styles to position: relative and altered some of your height elements.
I then added this Jquery function to run on document ready:
$(document).ready(function() {
var bottom = $(".mensaje-contenedor").height();
$(".chat-mensajes-contenedor").scrollTop(bottom);
})
To make messages always appear at the bottom use this CSS:
.chat-mensajes-contenedor-general {
min-height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.mensaje-contenedor {
align-self: flex-end;
}

Related

position sticky using javascript makes div goes outside the parent

I have a menu on the left that I want to be always sticky, I'm using javascript for that for IE11 support.
The problem I'm having is that the right div goes to the left when it's sticky and doesn't keep it's position, the second issue is that the .content div width grows when the right div is sticky.
For the javascript part, I don't know how to make the right div to stop when it reaches the footer.
EDIT:
I managed to solve the second issue, the code is updated, I also tried to add a right value for the right div so it sticks in its initial vertical position, but that's not working because it changes when the screen gets resized.
How can I solve this?
Edit 2:
For the javascript issue I found this post which helped me resolve my issue:
Make sticky/fixed element stop at footer
var sticky = document.getElementsByClassName("sticky-element")[0];
var stickyAnchor = sticky.parentNode;
var state = false;
function getAnchorOffset() {
return stickyAnchor.getBoundingClientRect().top;
}
updateSticky = function (e) {
if (!state && (getAnchorOffset() < 0)) {
sticky.classList.add("is-sticky");
sticky.parentElement.classList.add("has-sticky");
state = true;
} else if (state && (getAnchorOffset() >=0 )) {
sticky.classList.remove("is-sticky");
sticky.parentElement.classList.remove("has-sticky");
state = false;
}
}
window.addEventListener('scroll', updateSticky);
window.addEventListener('resize', updateSticky);
updateSticky();
.main-wrapper {
margin: 48px 48px 0 48px;
max-width: 1366px;
}
.wrapper {
width: 100%;
display: flex;
justify-content: space-between;
position: relative;
}
.wrapper.has-sticky .content{
margin-right: calc(199px + 72px);
}
.content {
flex: 0 1 1040px;
width: calc(1040px - 72px);
min-width: 1%;
margin-right: 72px;
height: 1200px;
background-color: #e6e9f0;
}
.nav-menu {
position: static;
flex: 0 1 199px;
width: 199px;
min-width: 199px;
color: white;
height: 300px;
background-color: #04246a;
right: 10%;
}
footer {
background-color: yellow;
height: 300px;
margin-top: 50px;
}
.is-sticky {
top: 0;
position: fixed;
}
<div class="main-wrapper">
<div class="wrapper">
<div class="content">
Main content
</div>
<div class="nav-menu sticky-element">
<nav>
Side content
</nav>
</div>
</div>
<footer>
Footer content
</footer>
</div>
Are you looking for this?
The problem on your code is that whenever you set the position of your right div to fixed it then looks for its relative parent and jumps to the upper left position inside the parent. In your case, the parent div was the .wrapper, that's why it keeps on jumping to the left side and overlaps your main content div.
I added a parent container for the .nav-menu so it will still be in the same position when scrolling. With this, your .nav-menu element won't be using the .wrapper as its main parent. This will create a smooth scroll without noticing any change in position.
Happy coding!
var sticky = document.getElementsByClassName('sticky-element')[0];
var stickyAnchor = sticky.parentNode;
var state = false;
function getAnchorOffset() {
return stickyAnchor.getBoundingClientRect().top;
}
updateSticky = function (e) {
if (!state && getAnchorOffset() < 0) {
sticky.classList.add('is-sticky');
state = true;
} else if (state && getAnchorOffset() >= 0) {
sticky.classList.remove('is-sticky');
state = false;
}
};
window.addEventListener('scroll', updateSticky);
window.addEventListener('resize', updateSticky);
updateSticky();
.main-wrapper {
margin: 48px 48px 0 48px;
max-width: 80%;
}
.wrapper {
width: 100%;
display: flex;
justify-content: space-between;
position: relative;
}
.content {
flex: 0 1 80%;
width: calc(80% - 24px);
min-width: 1%;
margin-right: 24px;
height: 1200px;
background-color: #e6e9f0;
}
.nav-container {
flex-grow: 1;
width: 20%;
min-width: 200px;
position: relative;
display: block;
}
.nav-menu {
color: white;
width: 100%;
min-width: inherit;
height: 300px;
background-color: #04246a;
}
.is-sticky {
top: 0;
position: fixed;
width: calc(20% - 97px);
}
<div class="main-wrapper">
<div class="wrapper">
<div class="content">Main content</div>
<div class="nav-container">
<div class="nav-menu sticky-element">
<nav>Side content</nav>
</div>
</div>
</div>
</div>
var sticky = document.getElementsByClassName("sticky-element")[0];
var stickyAnchor = sticky.parentNode;
var state = false;
function getAnchorOffset() {
return stickyAnchor.getBoundingClientRect().top;
}
updateSticky = function (e) {
if (!state && (getAnchorOffset() < 0)) {
sticky.classList.add("is-sticky");
state = true;
} else if (state && (getAnchorOffset() >=0 )) {
sticky.classList.remove("is-sticky");
state = false;
}
}
window.addEventListener('scroll', updateSticky);
window.addEventListener('resize', updateSticky);
updateSticky();
.main-wrapper {
margin: 48px 48px 0 48px;
max-width: 80%;
}
.wrapper {
width: 100%;
display: flex;
justify-content: space-between;
position: relative;
}
.content {
flex: 0 1 80%;
width: calc(80% - 24px);
min-width: 1%;
margin-right: 24px;
height: 1200px;
background-color: #e6e9f0;
}
.nav-menu {
position: static;
flex: 0 1 20%;
width: 20%;
min-width: 20%;
color: white;
height: 300px;
background-color: #04246a;
}
.is-sticky {
top: 0;
right:5%;
position: fixed;
}
<div class="main-wrapper">
<div class="wrapper">
<div class="content">
Main content
</div>
<div class="nav-menu sticky-element">
<nav>
Side content
</nav>
</div>
</div>
</div>

jquery animated slide show not animating

I have the following code for an image slider. It is a bit complicated because i want to use the slider code for multiple slider elements on the page. See below the code for one slider:
The problem i am having is described at the bottom.
$(document).ready(function(){
$('.vertical_img').first().addClass('display currentvertical_img').removeClass('invisable');
$('.horizontal_img').first().addClass('display currenthorizontal_img').removeClass('invisable');
$('.diagonal_img').first().addClass('display currentdiagonal_img').removeClass('invisable');
// image slider interaction with user
$('.right').click(function(){
next($(this).data('id'));
});
$('.left').click(function(){
previous($(this).data('id'));
});
});
function next(img_class){
var count;
$('.current'+img_class).animate({left: 0}, 500, function(){
console.log("animated?");
$('.current'+img_class).removeClass('display current'+img_class).addClass('invisable previous'+img_class);
if($('.previous'+img_class).is(':last-child')) {
count = $('.'+img_class).first().data('num');
$('.'+img_class).first().removeClass('invisable').addClass('display current'+img_class);
}
else{
$('.previous'+img_class).next().addClass('display current'+img_class).removeClass('invisable');
count = $('.previous'+img_class).next().data('num');
}
$('.'+img_class+'_slider').text(count+'/4');
$('.previous'+img_class).removeClass('previous'+img_class);
});
}
function previous(img_class){
var count;
$('.current'+img_class).removeClass('display current'+img_class).addClass('invisable previous'+img_class).animate({right: 0});
if ( $('.previous'+img_class).is(':first-child')) {
count = $('.'+img_class).last().data('num');
$('.'+img_class).last().removeClass('invisable').addClass('display current'+img_class);
}
else{
$('.previous'+img_class).prev().addClass('display current'+img_class).removeClass('invisable');
count = $('.previous'+img_class).prev().data('num');
}
$('.'+img_class+'_slider').text(count+'/4');
$('.previous'+img_class).removeClass('previous'+img_class);
}
.main_image_slide_container{
position: fixed;
left: 50px;
right:50px;
width: 500px;
height: 500px;
}
.image_slide_container_all_text_wrapper{
width: 100%;
height: auto;
overflow: overlay;
}
.image_slider_title{
float: left;
}
.image_slider_counter{
float: right;
}
.main_image_slide_container .image_slider_counter{
display: none;
}
.image_slide_container_all_text_wrapper .image_slider_counter{
display: block;
}
.slider_images_wrapper_window{
width: 100%;
height: auto;
position: relative;
}
.image_slider_controls{
position: absolute;
z-index: 10;
width: 50%;
height: 100%;
}
.left{
left: 0;
cursor: default;
}
.left:hover{
cursor: url(../../data/cursor_left.png) 40 30, move;
}
.right{
right: 0;
cursor: default;
}
.right:hover{
cursor: url(../../data/cursor_right.png) 40 30, move;
}
.slider_images_container{
width: 100%;
height: auto;
}
.slider_images_container img{
position: relative;
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main_image_slide_container">
<div class="image_slide_container_all_text_wrapper">
<div class="image_slider_title big_text font">Gravient Vertical</div>
<div class="image_slider_counter big_text font vertical_img_slider">1/4</div>
</div>
<div class="slider_images_wrapper_window">
<div class="image_slider_controls left" data-id="vertical_img"></div>
<div class="image_slider_controls right" data-id="vertical_img"></div>
<div class="slider_images_container">
<img class="vertical_img invisable" data-num="1" src="https://www.geeky-gadgets.com/wp-content/uploads/2010/06/google-mac-linux1.jpg">
<img class="vertical_img invisable" data-num="2" src="https://images.techhive.com/images/idge/imported/article/ctw/2012/10/19/samsung_chromebook_338-100391696-orig.jpg">
</div>
</div>
<div class="image_slider_counter big_text font vertical_img_slider">1/4</div> <!--mobile counter -->
</div>
So my current problem is that the images are not animating to the left. And i dont know why.. I am pretty sure my animate syntax is correct. I copy pasted it from the jquery website.
All suggestions and tips are welcome.
If something is not clear please let me know so i can clarify it!
You have missed the invisable css. Here is the working Example.
jsfiddle

slide right to left div on hover jquery

Good day,
I'm having trouble with jquery. i found a topic here that i want to learn using jquery slide right to left div http://jsfiddle.net/PXLJG/2/.
what i want to achieve is when hover, show hidden content on specific div.
i tried adding .addClass('active'); to the script.
here is the script i made
$(document).ready(function(){
$('.holdingbox').hover(function(){
var rightbox = $('.rightbox');
if (rightbox.hasClass('active')){
rightbox.stop().animate({width: '-0px'}, 1000).removeClass('active');
} else {
rightbox.stop().animate({width: '90px'}, 1000).addClass('active');
}
});
});
The problem now is when i hover on one div, all div shows up.Please see attached image.
Hope you guys can point me to right direction. thank you
You need to target the rightbox element in current element context i.e. this
You can either use context or .find() to target child element.
$('.holdingbox').hover(function() {
var rightbox = $('.rightbox', this); //$(this).find('.rightbox')
});
$(document).ready(function() {
$('.holdingbox').hover(function() {
var rightbox = $('.rightbox', this);
if (rightbox.hasClass('active')) {
rightbox.stop().animate({
width: '-0px'
}, 1000).removeClass('active');
} else {
rightbox.stop().animate({
width: '90px'
}, 1000).addClass('active');
}
});
});
div {
display: inline-block;
}
.holdingbox {
position: relative;
top: 0;
margin-left: 100px;
}
.leftbox {
position: relative;
top: 0;
left: 0;
display: inline-block;
font-size: 24px;
background-color: #ac193d;
color: #FFF;
font-weight: bold;
padding: 1px;
}
.rightbox {
position: relative;
display: inline-block;
overflow: hidden;
width: 0;
height: 30px;
vertical-align: top;
margin-right: 0;
}
.content {
width: 100px;
position: absolute;
background-color: #ac193d;
height: 29px;
left: 0;
top: 0;
right: 0;
color: #FFF;
padding-left: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="holdingbox">
<span class="rightbox"><span class="content">Kenyér</span></span>
<span class="leftbox">></span>
</div>
<div class="holdingbox">
<span class="rightbox">
<span class="content">Kenyér</span>
</span>
<span class="leftbox">></span>
</div>
Change code to this
You'll get children of the hovered element this way. Without using $(this) you target all '.rightbox' elements in document.
$('.holdingbox').hover(function(){
$(this).find('.rightbox').stop().animate({width: '90px'}, 1000)
}, function(){
$(this).find('.rightbox').stop().animate({width: '-0'}, 1000)
});

responsive height of div: shrink to a breakpoint then start growing again

I'm using an hero section to show some content.
It's responsive using the padding-bottom percentage technique and an inner absolute positioned container to center the content.
Now the catch: reaching a breakpoint, let's say 768px, and on lower window size I would like the box to start growing again.
I found some js/jQuery code around the web and was able to get the result but it only works if I load the page when the window is <768px. In that case it works brilliantly. But if the page is loaded in a larger window the below 768px resizing get lost.
This is the html:
<div class="row row-home-hero" id="hero">
<div class="cont">
<h1>Title</h1>
<h2>Subtitle</h2>
<div class="cta-hero-home">
» CTA1
<span class="cta-hero-spacer">or</span>
» CTA2
</div>
</div>
</div>
This is the JS.
It's a mess since it's a mix from different sources.
And I'm using Wordpress so I've to replace some $ with jQuery.
Please forgive me :)
function screenClass() {
if(jQuery(window).innerWidth() < 768) {
jQuery('.row-home-hero').addClass('small-hero');
} else {
jQuery('.row-home-hero').removeClass('small-hero');
jQuery('.row-home-hero').css("height", "");
}
}
// Fire.
screenClass();
// And recheck if window gets resized.
jQuery(window).bind('resize',function(){
screenClass();
});
if (document.documentElement.clientWidth < 768) {
var $li = jQuery('.small-hero'), // Cache your element
startW = $li.width(); // Store a variable reference
function setMarginDiff() {
area = 500000;
width = jQuery('.small-hero').width();
jQuery('.small-hero').height(Math.ceil(area/width/1.7));
}
setMarginDiff(); // Do on DOM ready
jQuery(window).resize(setMarginDiff); // and on resize
}
And this is the CSS
.row-home-hero {
background-position: center;
-webkit-background-size: cover;
background-size: cover;
background-repeat: no-repeat;
position: relative;
background-color: red;
}
.row-home-hero:before {
display: block;
content: "";
width: 100%;
padding-top: 46%;
}
.row-home-hero .cont {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 40%;
text-align: center;
}
a.cta-hero-link {
display: block;
width: 100px;
max-width: 80%;
line-height: 40px;
background: white;
color: #1b9fdd;
text-transform: uppercase;
text-decoration: none;
margin: 10px auto;
text-align: center;
font-weight: 500;
box-shadow: 0px 0px 7px 1px rgba(0,0,0,.4);
}
#media screen and (max-width: 768px) {
.row-pre-footer .cont div {
width: 100%;
padding: 0 5%;
float: none;
margin: 0 auto 30px;
}
.progetto-footer, .loghi-footer {
width: 100%;
max-width: 320px;
margin: 0 auto 30px;
float: none;
}
.double-box .tib-tab {
float: none;
width: 90%;
margin: 5% auto;
padding-bottom: 90%;
}
.tib-box h2, .tab-box h2 {
font-size: calc(28px + (46 - 28) * (100vw - 320px) / (768 - 320));
margin-bottom: 18vw;
}
.double-box-inner p {
font-size: 22px;
line-height: 30px;
}
.row-home-hero.small-hero {
height: 500px;
}
.row-home-hero:before {
display: block;
content: "";
width: 100%;
padding-top: 0;
}
}
And this is a working demo
Thanks!
I moved the if (document.documentElement.clientWidth < 768) { block inside the resize event. So that it gets called whenever the window is resized.
In the original version, it would only get called when the page was loaded (and only if the screen was smaller than 768). With this adjustment, it will always be rechecked when resized.
I also merged all your code into one smaller function.
var breakpoint = 768
var area = 500000
var target = $('.row-home-hero')
$(window).bind('resize', function() {
if(window.innerWidth < breakpoint) {
var width = target.width()
target.addClass('small-hero')
target.height(Math.ceil(area / width / 1.7))
} else {
target.removeClass('small-hero')
target.css('height', '')
}
})
.trigger('resize')

How do I check whether the right/left edge of an element is overlapping the side of it's container?

I'm trying to display a right / left navigation arrow within a container (the arrows replace the existence of a scrollbar) when the corresponding edge of the content overlaps the container's sides.
Also, when the content is scrolled all the way to the end and can't scroll any further, the arrow should disappear.
My problem is, I'm confused as to how I write the function to check whether the element's contents are overlapping one edge or the other to hide one arrow or the other.
I started writing logic like this:
function setArrows(elem){
if (elem.scrollLeft() > 0) { //scroll position is greater than zero
// show left arrow
}
if () { //scroll position is less than zero
//show right arrow
}
}
but that doesn't seem to be the right logic. It sounded simpler in my head before I went to actually write the function.
How do I check whether the right/left edge of an element is overlapping the side of it's container?
Here's a Stack Snippet:
$('#wrapper').scroll(function(){
//check edges
});
div {
padding: 0px;
margin: 0px;
}
#wrapper {
width: 500px;
height: 100px;
background-color: blue;
overflow-x: scroll;
overflow-y:hidden;
}
#content {
width: 1000px;
height: 100px;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="wrapper">
<div id="content">
</div>
</div>
You need to check if the content width minus the scrollLeft is greater than the wrapper width. If it is show the right scroller..
Something like this
$(function() {
var content = $('#content'),
arrows = $('.arrow'),
wrapper = $('#wrapper').scroll(function() {
//check edges
// handle left arrow
if (this.scrollLeft > 0) {
arrows.filter('.left').addClass('visible');
} else {
arrows.filter('.left').removeClass('visible');
};
// handle right arrow
if (content.outerWidth() - this.scrollLeft > wrapper.width()) {
arrows.filter('.right').addClass('visible');
} else {
arrows.filter('.right').removeClass('visible');
};
});
arrows.on('click', function() {
if ($(this).is('.left')) {
wrapper[0].scrollLeft -= 100;
} else {
wrapper[0].scrollLeft += 100;
}
return false;
});
// initialize
wrapper.trigger('scroll');
});
div {
padding: 0px;
margin: 0px;
}
#wrapper {
width: 500px;
height: 100px;
background-color: blue;
overflow-x: hidden;
overflow-y: hidden;
position: relative;
}
#content {
width: 1000px;
height: 100px;
background: url('http://lorempixel.com/1000/100/abstract/2') 0 0 no-repeat;
}
#full-container {
position: relative;
display: inline-block;
}
.arrow {
position: absolute;
top: 0;
bottom: 0;
width: 40px;
background-color: black;
display: none;
z-index: 100;
cursor: pointer;
color: #fff;
text-align: center;
line-height: 100px;
}
.arrow.visible {
display: block;
}
.arrow.left {
left: 0
}
.arrow.right {
right: 0
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="full-container">
<div class="arrow left"><</div>
<div id="wrapper">
<div id="content"></div>
</div>
<div class="arrow right">></div>
</div>

Categories

Resources