Scrollbar on top of DIV and nowrap container - javascript

I'm familiar with this StackOverflow question & confirmed answer.
However, checking their fiddle here, I've noticed one thing I really really need. The container (aka div2 class element) doesn't have no-wrap property which I would really really need for my tables inside #container (nowrap for having tables in one row)
My code:
CSS:
.subnetTable {
width: 150px;
display: inline-table;
border:1px solid #E8E8E9;
margin: 2px;
padding: 2px;
white-space: normal;
}
#scroller_wrapper, #container_wrapper{
width: 98%; border: none 0px RED;
overflow-x: scroll; overflow-y:hidden;
}
#scroller_wrapper{height: 16px; }
#scroller { width: 500px; height: 16px; }
#container { width: 500px; overflow: auto;}
HTML:
<div id="scroller_wrapper">
<div id="scroller">
</div>
</div>
<div id="container_wrapper">
<div id="container">
<table class="subnetTable"><tr><td>12341234</td></tr></table>
<table class="subnetTable"><tr><td>12341234 123412341234 1234123412 34123412341 2341234123412 341234123 412341234</td></tr></table>
<table class="subnetTable"><tr><td>12341234</td></tr></table>
<table class="subnetTable"><tr><td>12341234 123412341 2341234123412 34123412341234 123412341 23412341234</td></tr></table>
<table class="subnetTable"><tr><td>12341234 1234123412 341234123412 34123412341234 123412341 23412341234</td></tr></table>
<table class="subnetTable"><tr><td>12341234 123412341 2341234123412 34123412341234 123412341 23412341234</td></tr></table>
</div>
</div>
JAVASCRIPT (jQuery):
// SCROLLBARS
$(function(){
$("#scroller_wrapper").scroll(function(){
$("#container_wrapper").scrollLeft($("#scroller_wrapper").scrollLeft());
});
$("#container_wrapper").scroll(function(){
$("#scroller_wrapper").scrollLeft($("#container_wrapper").scrollLeft());
});
});
// CONTAINER RESIZE
$(window).load(function () {
$('#scroller').css('width', ($(window).width() - 10) );
$('#container').css('width', ($(window).width() - 10) );
});
MY JsFiddle Code & the Problem:
click here.
The problem appears, when you add white-space: nowrap; to #container class. Instead of correct result, it creates another scrollbar at bottom which I wouldn't like. IT does move tables to one row but it doesn't create correct scrollbar at bottom or top anymore (replacing tables with only text doesn't work either).
Please help me out!

With you code as-is the solution is to put a <br> just before the fourth table or wrapping the first three and second three tables in a block level element such as a div.
Why?
Each table is inline - so setting #container to not wrap will make all the inline tables extend out to the right. Adding a break will force it to break as expected.
Note
Please consider using DIVs or some other semantic element rather than tables - your code does not appear to be tabular data.

Related

Fixed row/column header with css and javascript

I need a layout with fixed column/row header. After some "trial and error" I came up with this solution (see jsfiddle). Only the lower right pane is scrollable, and the headers are moved using javascript.
Everything is fine in Chrome, but in IE/Edge the scrolling is laggy: the left and the right part are not scrolled on the same time but with a minimal delay (especially it the content is "big") which is annoying. Do you see any solution? I have to find another way to achieve the result (and in this case do you have any suggestion)?
$(function() {
init();
});
function init(){
var div1=$("#mainContainer");
var oldScrollTop = $(div1).scrollTop();
$(div1)
.scroll( function () {
if (oldScrollTop == $(div1).scrollTop()){
scrollRowTableHeader(); //horizontal scroll
}else {
oldScrollTop = $(div1).scrollTop();
scrollColumnTableHeader(); //vertical scroll
}
});
}
function scrollColumnTableHeader() {
var vScrollPanel = $("#mainContainer"),
headerPanelContent = $("#headerPanelContent"),
colHeaderPanelContent = $("#colHeaderPanelContent");
var colHeaderPanelContent2 = document.getElementById('headerContent');
colHeaderPanelContent2.style.top = (0 - vScrollPanel.scrollTop())+"px";
};
function scrollRowTableHeader() {
var vScrollPanel = $("#mainContainer"),
headerPanelContent = $("#headerPanelContent"),
colHeaderPanel = $("#colHeaderPanel");
var headerPanelContent2 = document.getElementById('headerPanelContent');
headerPanelContent2.style.left = (0 - vScrollPanel.scrollLeft())+"px";
};
#container {
/*background-color: green;*/
display: flex;
}
.item {
background-color: white;
border: 1px solid black;
flex-grow: 0;
}
.bigContent{
height: 1000px;
width: 1000px;
}
.scroll{
overflow: auto;
height: 300px;
width: 500px;
}
.colheader{
height: 300px;
width: 200px;
/*position: relative;*/
z-index: 1;
overflow:hidden;
display: inline;
border: solid 1px;
}
.headerContent{
background: lightgrey;
height: 1000px;
width: 200px;
position: relative;
border: solid 1px;
}
.rowHeaderContent{
background: whitesmoke;
height: 100px;
width: 200px;
position: relative;
}
.rowColHeaderContent{
background: lightyellow;
height: 100px;
width: 200px;
border: solid 1px;
}
.headerPanel{
overflow: hidden;
width: 500px;
border: solid 1px;
}
.tableProperties{
table-layout: fixed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="container">
<div id="header" class="header">
<div class="rowColHeaderContent">
<table class="tableProperties">
<tr><td>Row/Col Header</td></tr>
</table>
</div>
</div>
<div id="headerPanel" class="headerPanel">
<div id="headerPanelContent" class="rowHeaderContent">
<table width="500px" class="tableProperties">
<colgroup><col width="50"><col width="40"><col width="40"><col width="40"><col width="45"><col width="40"></colgroup>
<tr><td>Some content (header)</td><td>Some content</td><td>Some content</td><td>Some content</td><td>Some content</td><td>Some content</td></tr>
</table>
</div>
</div>
</div>
<div id="container">
<div id="colheader" class="colheader">
<div id="headerContent" class="headerContent">
<table width="500px" class="tableProperties">
<tr><td>Column Header</td></tr>
<tr><td>Column Header</td></tr>
<tr><td>Column Header</td></tr>
<tr><td>Column Header</td></tr>
<tr><td>Column Header</td></tr>
<tr><td>Column Header</td></tr>
</table>
</div>
</div>
<div id="mainContainer" class="item scroll">
<div class="bigContent">
<table width="500px" class="tableProperties">
<colgroup><col width="50"><col width="40"><col width="40"><col width="40"><col width="45"><col width="40"></colgroup>
<tr><td>Some content</td><td>Some content</td><td>Some content</td><td>Some content</td><td>Some content</td><td>Some content</td></tr>
</table>
</div>
</div>
</div>
So, this is not a direct answer to your really complex issue, but here goes..
First of all looks like you are in the first steps of trying to create a fixed-column and fixed-row table. It might seem to be working at first, but, trust me, the way you are trying to achieve it is not going to work well and the reason is that since table-cell widths are set arbitrarily for each table, you won't be able to align the header table with the content table below it. So, you will either have to follow a different approach than the current way you are taking - tips imminent.
First things first, the problem with a lot of data in this kind of situation is more noticeable in IE11 - the lag is lighter in IE edge and there is no lag in other browsers. In your case you can use debouncing in order to reduce the js calls while scrolling.
setInterval(function(){
// Scroll stuff here
}, 2)
The interval doesn't have to be high, a light lag will be visible, but it will be a great improvement compared to how (I suppose) it currently works.
Also try using Javascript functions that work with minimum impact, eg use .attr instead of .style; also try using CSS3 transforms instead of normal transforms.
So concerning the different approach - you have to somehow the scrolling header and content be in the same table - ideally the fixed column as well. Here are some tips. It is necessary to remove word wrapping within the table cells by using white-space:nowrap for the following tips to work as intended. The concept might be difficult to grasp, but once you encounter each issue they will make sense.
First of all add some top padding to the table that will accommodate the header elements described next. Create both p and span elements inside the header cells and place the same header content in both of them. Absolutely position the span elements using CSS3 transforms towards the top.
The 'p' elements will remain static, but not visible - hide them using visibility, opacity and height:0. Paragraph elements will be used in case the th content exceeds the td content.
In order to scroll everything with decent performance you will HAVE to use CSS3 transforms to scroll the span elements (careful: the span elements!) after you cache them on page load.
Hope these tips help you out, for any questions feel free to ask - it will be difficult to digest at first but it will make sense.
If you want Only the lower right pane is scrollable?
I just used css like :-
.headerContent{
background: lightgrey;
height: 1000px;
width: 200px;
position: static;
border: solid 1px;
}
Changed position: relative into static...

Make Div fixed bottom & scrollable

I want to have a long page, with a fixed top 100px div, and a fixed 50px bottom div. However, I want the bottom div to scroll as you scroll down the page.
Its hard to explain, but the best example of this is on the front page of PayPal.com
On the first page load, the bottom div looks like it is fixed, and as you adjust the height of the browser window, that div stays at the bottom. Yet as you scroll down the page it is not fixed.
Can anyone explain how they have done this? I am trying to re-create something similar, but cant see how they have managed it.
As far as I can see they have this html...
<div id="fixed-top">
<header class="table-row">
// header content
</header>
<div class="table-row table-row-two">
// Video content
</div>
<div class="table-row">
//bottom content
</div>
</div>
And this CSS...
#fixed-top {
height: 100%;
width: 100%;
display: table;
position: relative;
top: 0;
left: 0;
z-index: 1;
}
.table-row {
display: table-row;
}
But that alone doesn't do it. I also can't see any js thats getting window height and applying it to the main fixed div.
Help! :)
EDIT:
Have just found a way to do it with javascript, controlling the height of the middle row using the window height, minus the 150px for the header and third row.
jQuery(document).ready(function(){
$('div.table-row-two').css({'height':(($(window).height())-150)+'px'});
$(window).resize(function(){
$('div.table-row-two').css({'height':(($(window).height())-150)+'px'});
});
});
But saying that, Zwords CSS only method seems like a winner.
From what I understand, you are looking for something like a sticky footer. So basically if the content is not enough, the footer should go sit at the bottom like its fixed, but if content comes in, it should scroll down like other content.
Try this - http://css-tricks.com/snippets/css/sticky-footer/
First off, you'll need to set the height of the body and html tag, otherwise the table won't take the full screen. Then I altered your code, made it a bit easier.
HTML:
<div id="fixed-top">
<header>
// header content
</header>
<div>
// Video content
</div>
<div>
//bottom content
</div>
</div>
CSS:
html, body {
margin: 0;
padding: 0;
height: 100%;
min-height: 100%;
}
#fixed-top {
display: table;
width: 100%;
height: 100%;
}
#fixed-top > * { /* makes all the direct children of #fixed-top a table row*/
display: table-row;
background: lightblue;
}
#fixed-top > *:nth-child(1) {
background: lightgreen;
height: 40px;
}
#fixed-top > *:nth-child(3) {
background: lightgreen;
height: 25%;
}
You can either set the height to a fix height (in px) or percentages. If you only give two of the three rows a height, the third one will automaticly fill up the rest space.
Also, check this demo.
Check this fiddle / Fullscreen
Using display:table;,display:table-row;,min-height to adjust to screen
HTML
<div class="wrapper">
<div class="row">menu</div>
<div class="row">content</div>
<div class="row">footer</div>
</div>
<div class="wrapper">
<div class="row">content1</div>
<div class="row">content2</div>
<div class="row">content3</div>
</div>
CSS
html,body,.wrapper{
width:100%;
height:100%;
margin:0px auto;
padding:0px;
}
.wrapper{
display:table;
border:1px solid black;
}
.wrapper .row{
display:table-row;
background-color:rgb(220,220,220);
}
.wrapper .row:nth-of-type(1){
min-height:15px;
}
.wrapper .row:nth-of-type(2){
height:100%;
background-color:white;
}
.wrapper .row:nth-of-type(3){
min-height:15px
}
You can do this easily with jQuery using $(window).height() and subtracting your footer/header's heights. See Fiddle for an example.

CSS/Javascript: Keep a div size based on container size

I have a div which contains 2 divs, one has fixed height.
I want to make sure that the 2nd div's height is exactly as much as the height of the container div minus the other div's height. This height can't be manually set because it's often resized.
<div id="container" style="height: 50%">
<div id="header" style="height: 30px;">
</div>
<div id="content">
</div>
</div>
i have tried with jquery on resize but i think i wrote something wrong:
$(document).on("resize", "#container", function (event) {
$('#content').height($('#container').height()-$('#header').height());
});
Is there any way (Javascript, CSS) to achieve this?
An alternative to the jQuery method is CSS Flexbox:
#container {
display: flex;
flex-direction: column;
}
#content {
flex: 1;
}
See the demo. Unfortunately, this will only work in browsers supporting the latest Flexbox syntax. (http://caniuse.com/#search=flexbox) Backward compatible code is possible using old syntaxes as well, but will be sightly more involved. See David Storey's article at http://coding.smashingmagazine.com/2013/05/22/centering-elements-with-flexbox/ for more on how to do that.
Your main problem seems to be that you have to size the element initially and then keep listening to the resize event:
function handleResize() {
$('#content').height($('#container').innerHeight()-$('#header').height());
}
$(window).on("resize", handleResize);
handleResize();
Also, the resize event should be attached directly to the window.
Otherwise, I recommend the use of innerHeight() for the container as that takes into account padding.
Also I made some fixes to your CSS for this to fully work:
#container {
position: absolute;
width: 100%;
height: 50%;
}
See full fiddle here: http://jsfiddle.net/kjcY9/1/
I have a pure CSS solution for you,
Check out that Working Fiddle
HTML:
<div id="container">
<div id="header"></div>
<div id="content"></div>
</div>
CSS:
#container {
height: 300px; /*Whatever fixed height you want*/
}
#container:before {
content:'';
float: left;
height: 100%;
}
#header {
height: 30px;/*Whatever fixed height you want, or not fixed at all*/
background-color: red;
}
#content {
background-color: blue;
/*No height spesified*/
}
#content:after {
content:'';
clear: both;
display: block;
}

How to stack divs beside each other to create a carousel

I am trying to create a carousel, where clicking on any element will slide it leftwards, simultaneously sliding the right element into viewport. For that, I need to have the divs stacked side by side. I am trying it out as a float based layout (see Fiddle ).
Problem is that here clicking the red colored div slides it leftward alright, but not the green element leftwards. This is probably due to the fact that they are actually lying below another, as visible when the overflow: hidden is removed from #cont's style. How elese to stack them side by side so that sliding one leftward automatically slides the next one leftwards as well? (Creating the to-be-next element on the fly while clicking and animating it into viewport is a no-no, the element should be present in the DOM!)
I'd suggest you use a plugin, as there is more to this than you may realize. There are many plugins out there for this, here's a list to get you started: http://www.tripwiremagazine.com/2012/12/jquery-carousel.html
I modified your Javascript, HTML, and CSS to get you pointed in the right direction:
http://jsfiddle.net/nf5Dh/2/
You need a container contContent, positioned absolutely, and that container gets moved within the container div. You just float the elements in contContent to get them next to each other.
HTML:
<div id='cont'>
<div id="contContent">
<div id='i1'></div>
<div id='i2'></div>
<div id='i3'></div>
</div>
</div>
CSS:
#cont {
width: 50px;
padding-top: 10px;
background: blue;
height: 50px;
overflow: hidden;
position: relative;
}
#contContent {
height: 50px;
width: 150px;
position: absolute;
top: 0;
left: 0;
}
#contContent > div {
float: left;
display: inline-block;
height: 50px;
width: 50px;
}
#i1 { background: red; }
#i2 { background: green; }
#i3 { background: yellow; }
And the JS:
$("#contContent > div").click(function(){
$("#contContent").animate({left: "-=50px"},1000);
});
You'd probably be better off using an ul instead of all divs, this is at least more semantically correct, though not technically necessary.
<div id="carousel">
<ul id="carouselContent">
<li id="slide1"></li>
<li id="slide2"></li>
<li id="slide3"></li>
</ul>
</div>
This:
#cont {
white-space:nowrap;
overflow: hidden;
}
.pane { // or whatever the slide divs are called. get rid of the float.
float: none;
display: inline-block;
*zoom:1;
*display:inline;
}
You can use that carousel where you can generate javascript for the carousel http://caroufredsel.dev7studios.com/configuration-robot.php
I've used http://sorgalla.com/jcarousel/ for things like this in the past, that's based on postion: relative and left/right offsets. Probably easier than messing with floats.
You can try using a list item instead, and display them inline.

How to refresh the size of a div after adding elements to it

I have an element like this:
<div id="content" style="border: 2px solid black">
</div>
And through JQuery I add some new stuff:
$("#content").append($('<div></div>').addClass("box"));
where
.box { margin: 10px; padding: 10px; border: 1px solid black }
But the outer div does not resize when I do this, so I get an inner box that is sticking out of a solid outer box. How can I get the outer box to resize itself when I add this inner box?
Correct the selector if it's not a typo
$("#content") // id="content" (correct)
$("content") // tagName = content
And change the display of the div to inline-block
#content {
display: inline-block;
}
Then the div will not occupy the whole row.
try this:
js
$('#content').append('<div class="box"> </div>');
html
<div id="content" style="border:2px solid black;overflow:hidden;">
</div>
I hope his help!
#content is not resizing, since it's width is probably set in your CSS.
Either make it wider, or specifically size it appropriately.
Looks like #content must be over 40px wide, since the inner div has 10 margin and 10 padding, which is 20 on the left and 20 on the right.
So, something like:
$("#content").css("width","100%").append($('<div></div>').addClass("box"));
Or better yet, set up your CSS at the right width to begin with:
#content { width: ... ; }
If you are floating .box within #content then set the overflow of #content to auto(or hidden), otherwise the outer box doesn't "see" the floating inner boxes:
#content { overflow: auto; }
In my case I added:
#property { overflow: auto; }
and now size of elements is being recalculated when I show or hide elements.

Categories