Guys, I have the following HTML. Is it possible for the #underdiv to scroll under the #topdiv? I want to achieve the effect of having a list of items and to be able to scroll it up and down while keeping the #topdiv always visible on top of it. Can it be done just with the CSS or do I have to add some Javascript magic? I also have JQuery and JQueryMobile (as this is meant for an iOS device) included in the file but I kept them out to make the HTML look simpler.
Thanks in advance for helping me out!
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<style>
#underdiv {
background-color: red;
position: relative;
top: -40px;
width: 80%;
margin: 0 auto;
}
#topdiv {
background-color: yellow;
}
</style>
</head>
<body>
<div id="topdiv">
<h1>Random title</h1>
<p>This is a random paragraph bla bla bla bla yada yada yada</p>
</div>
<div id="underdiv">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
<li>Item 13</li>
<li>Item 14</li>
<li>Item 15</li>
<li>Item 16</li>
<li>Item 17</li>
<li>Item 18</li>
<li>Item 19</li>
<li>Item 20</li>
</ul>
</div>
</body>
</html>
it's possible, though the scrollbar disappears under too;
ul {
margin: 0;
padding: 40px 0 0 30px;
}
#underdiv {
background-color: red;
width: 80%;
margin: 0 auto;
height: 200px;
overflow: auto;
margin-top: -40px;
}
#topdiv {
background-color: yellow;
padding: 1px; /* to stop margins collapsing */
position: relative;
}
remove position:relative from underiv and add position:fixed to topdiv.
Look at the resut here
Related
I have a list of items in a container. The container takes the full width of the parent, allowing the items to overflow horizontally if needed. Here's what it looks like:
ul {
list-style: none;
display: flex;
overflow-x: auto;
padding: 0;
margin: 0;
border: 1px dotted black;
}
li {
margin-right: 10px;
}
li:last-child {
margin-right: 0;
}
a {
display: block;
text-decoration: none;
white-space: nowrap;
padding: 4px 8px;
color: black;
background-color: white;
border: 1px solid black;
}
a.active {
background-color: blue;
}
<ul id="container">
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
In the list of items, there is one that has the .active class. I want to horizontally scroll the container in a way such that this item is exactly centered. To do this, I wrote the following function:
function toMiddle(element, container) {
if (container === undefined) {
container = window;
}
var elementRect = element.getBoundingClientRect();
var absoluteElementLeft = elementRect.left;
var middleDiff = (elementRect.width / 2);
var scrollLeftOfElement = absoluteElementLeft + middleDiff;
var scrollX = (scrollLeftOfElement - (container.getBoundingClientRect().width / 2));
container.scrollTop = 0;
container.scrollLeft = scrollX;
}
And I'm trying to call this to center the container as follows:
toMiddle(document.getElementById("element"), document.getElementById("container"));
Unfortunately, this doesn't seem to work properly. Any idea how I can fix this? And what exactly am I doing wrong here?
Please note, scrollIntoView() works perfectly well, but it scrolls the whole page vertically as well, which is not an acceptable thing for my use case.
You can use .offsetLeft method to find distance from left instead of .getBoundingClientRect() method. And count width of active item with .clientWidth method instead of .width and I also added .resize method for active item keeping it centered.
Useful links:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetLeft
https://developer.mozilla.org/en-US/docs/Web/API/Element/clientWidth
function toMiddle(container_id) {
var container = document.getElementById(container_id);
var elementRect = document.querySelector('#' + container_id + ' .active');
var absoluteElementLeft = elementRect.offsetLeft;
var middleDiff = (elementRect.clientWidth / 2);
var scrollLeftOfElement = absoluteElementLeft + middleDiff;
var scrollX = (scrollLeftOfElement - (container.clientWidth / 2));
container.scrollTop = 0;
container.scrollLeft = scrollX;
}
/*Initialize on page load*/
toMiddle("container");
/*Window resize then active item tab should be centered*/
var timeout = 0;
window.onresize = () => {
clearTimeout(timeout);
timeout = setTimeout(() => {
toMiddle("container");
}, 500)
}
/*Click on item tab then should be centered*/
var allItem = [...document.querySelectorAll('#container li a')]
allItem.forEach(element => {
element.addEventListener('click', (e)=> {
allItem.forEach(ele => {
ele.classList.remove('active');
})
/*Add active class*/
e.target.classList.add('active');
/*Call the function for set item tab in centered*/
toMiddle("container");
})
});
ul {
list-style: none;
display: flex;
overflow-x: auto;
padding: 10px;
margin: 0;
border: 1px dotted black;
position: relative;
}
li {
margin-right: 10px;
}
li:last-child {
margin-right: 0;
}
a {
display: block;
text-decoration: none;
white-space: nowrap;
padding: 4px 8px;
color: black;
background-color: white;
border: 1px solid black;
transition: 0.5s ease-in;
}
a.active {
background-color: #0156e8;
border: 1px solid #00389a;
color: #fff;
}
<ul id="container">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
<li>Item 11</li>
<li>Item 12</li>
<li>Item 13</li>
<li>Item 14</li>
<li>Item 15</li>
<li>Item 16</li>
<li>Item 17</li>
<li>Item 18</li>
<li>Item 19</li>
<li>Item 20</li>
<li>Item 21</li>
<li>Item 22</li>
<li>Item 23</li>
<li>Item 24</li>
<li>Item 25</li>
<li>Item 26</li>
<li>Item 27</li>
<li>Item 28</li>
<li>Item 29</li>
<li>Item 30</li>
<li>Item 31</li>
<li>Item 32</li>
<li>Item 33</li>
</ul>
I would like to render the items horizontally while the page load, refer to following images
<section
tabindex="-1"
class="relative mx-8 mt-10 mb-20 max-w-7xl focus:outline-none sm:mx-16 md:mx-20 lg:mx-24 xl:mx-auto"
>
<ul
class="h-full w-full list-none columns-1 gap-4 space-y-12 overflow-hidden pb-32 md:columns-2 lg:columns-3 lg:gap-8 xl:columns-4"
>
<ExploreCard
v-for="(post, index) in posts.data"
:key="index"
:post="post"
:canLike="this.canLike"
/>
</ul>
</section>
Currently
Expected
Something like this,
https://reactjsexample.com/rendering-columns-from-a-list-of-children-with-horizontal-ordering/
I am looking for a Js, Vue, or CSS solution.
I end up with a package solution and it works perfectly fine!
DaPotatoMan/vue-next-masonry
and this is how it looks like
<masonry
:cols="{ default: 4, 1024: 3, 768: 2, 640: 1 }"
:gutter="{ default: 40, 1024: 30, 768: 20 }"
>
<div v-for="(post, index) in posts.data" :key="index" class="mb-10">
<ExploreCard
v-for="(post, index) in posts.data"
:key="index"
:post="post"
:canLike="this.canLike"
/>
</div>
</masonry>
In this way, all the post is rendered in horizontal order !
I would advise that you use tailwind class utility of grid to create a grid container:
https://tailwindcss.com/docs/display#:~:text=Use%20grid%20to%20create%20a%20grid%20container.
This is an answer with pure CSS from #haltersweb
https://stackoverflow.com/a/37063940/17737657
CSS-only masonry layout
display: inline-block
ul {
margin-left: .25em;
padding-left: 0;
list-style: none;
}
li {
margin-left: 0;
padding-left: 0;
display: inline-block;
width: 30%;
vertical-align: top;
}
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
<li>item 5</li>
<li>item 6</li>
<li>item 7</li>
<li>item 8</li>
<li>item 9</li>
</ul>
display: flex
ul {
margin-left: .25em;
padding-left: 0;
list-style: none;
display: flex;
flex-wrap: wrap;
}
li {
margin-left: 0;
padding-left: 0;
width: 33.3%;
}
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
<li>item 5</li>
<li>item 6</li>
<li>item 7</li>
<li>item 8</li>
<li>item 9</li>
</ul>
I am attempting to use two selectable lists with the same selectable class, I want to toggle all the items irrespective of the parent list when a selection is made.
Currently when I select an item, only the selections from the same list get toggled/unselected, but the selected item from the other list remains selected.
Is there any way to have these as two separate lists but behave as the same one, for this specific function?
Any help would be appreciated. Thank You.
$( ".selectable" ).selectable();
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<style>
div {border:1px solid black;}
.selectable .ui-selecting { background: #FECA40; }
.selectable .ui-selected { background: #F39814; color: white; }
.selectable { list-style-type: none; margin: 0; width: 60%; }
.selectable li { margin: 3px; padding: 0.4em; font-size: 1.4em; height: 18px; }
</style>
<div id="div1">
<h4>List 1</h4>
<ul class="selectable">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
</ul>
</div>
<div id="div2">
<h4>List 2</h4>
<ul class="selectable">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
</ul>
</div>
I suppose what I was trying to achieve here is what is defined under a different widget, you would call menu.
Changing the script to:
$(".selectable").menu();
gave the desired result.
I have a scrollable dropdown menu and I want to keep the last item fixed and always visible on top while all the other items would scroll. However, with my solution it's really jumpy. Here's what I have so far:
HTML:
<ul class="menu">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li class="fixed">Item 10</li> <!-- this item will be fixed and always on top -->
</ul>
Javascript:
this.$('.menu').on('scroll', function() {
if (stickyItem = $('.fixed')) {
//get the y position of the parent
topHeight = stickyItem.parent().offset().top;
//how far apart the sticky item should always be from the top of the bar
heightDiff = stickyItem.parent().height() - stickyItem.height();
if ((stickyItem.offset().top - topHeight) < heightDiff) {
heightApply = heightDiff + ( heightDiff - (stickyItem.offset().top - stickyItem.parent().offset().top));
stickyItem.css('top', (heightApply)+'px');
}
}
});
CSS:
ul li.fixed {
position: absolute;
bottom: 0;
}
Is there an easier way to accomplish what I'm trying to do? Thanks!
I have not tested anywhere besides chrome, but here's a pure CSS solution for your problem:
html,body{height:100%; margin:0; padding:0}
ul {margin: 0; padding:0; height:auto;
/*this padding bottom allows the penultimate element to be displayed*/
padding-bottom:39px}
ul li {padding:10px; background:#eee; color:#333;
font-family:sans-serif; border-bottom:1px solid #CCC; }
ul li.fixed { /*you could also use the :last pseudo selector*/
width:100%;
position: fixed;
bottom: 0;
background:lightblue;
}
https://jsfiddle.net/patareco/kb99u78p/1/
Hope it does what you intended.
I have recently started designing a mobile website using media queries and browsing a few websites to see what they've done it seems accordion navigation menus are the way to go, scaling up to a normal horizontal navigation bar. I have browsed and browsed the internet looking for an accordion walkthrough but I can not seem to find one that explains it well enough.
A good example is the one from microsoft on their website. Here is my code so far:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<style>
body {
padding: 0;
margin: 0;
}
#topMenu {
height: 50px;
width: 100%;
background-color: #cde;
display: block;
}
nav {
width: 100%;
height: auto;
display: block;
margin: 0;
padding: 0;
}
nav a {
text-decoration: none;
padding-left: 40px;
}
nav ul {
list-style: none;
display: block;
margin: 0;
padding: 0;
background-color: #ccc;
}
nav ul li {
display: block;
width: 100%;
padding: 20px 0px 20px 0px;
border-top: 2px solid #abc;
}
nav ul ul {
height: 0;
overflow: hidden;
padding-top: 0px;
}
nav ul ul li a {
padding-left: 100px;
}
</style>
</head>
<body>
<div id="topMenu"></div>
<nav>
<ul>
<li>Link</li>
<li>Link
<ul>
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
<li>Link 4</li>
<li>Link 5</li>
<li>Link 6</li>
<li>Link 7</li>
</ul>
</li>
<li>Link
<ul>
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
<li>Link 4</li>
<li>Link 5</li>
<li>Link 6</li>
<li>Link 7</li>
</ul>
</li>
<li>Link
<ul>
<li>Link 1</li>
<li>Link 2</li>
</ul>
</li>
<li>Link</li>
<li>Link</li>
<li>Link</li>
</ul>
</nav>
</html>
These navigation bars have submenus [nav ul ul] that slide out when nav ul li is clicked. I was hoping somebody could point me in the right direction as to how I go about making a slide down sub menu on click, or help me with the code.
I thought there may have been a basic one people could start using and edit to customise themselves.
Thanks for any help.
There is no need for Javascript - you may use a Checkbox instead.
Check out: http://codepen.io/TimPietrusky/pen/CLIsl
If you still want to do it with Javascript go for something like this:
// asuming, that nav-items that should trigger slidedown will have "#" as href
// while actual nav-items will have URLs
$('nav li a[href="#"]').on('click', function (e) {
// prevent Click from redirecting
e.preventDefault();
// get the next ul after the li a clicked
if ($(this).hasClass('visible')) {
$(this).next('ul').slideUp(200).removeClass("visible");
} $(this).next('ul').slideDown(200).addClass("visible");
});
CSS animation for height form 0 to auto wont work. See: How can I transition height: 0; to height: auto; using CSS?
Check this out
https://jsfiddle.net/nqamazgz/3/
Unfortunately CSS does not have any click events, instead you will need to use JavaScript and/or jQuery. I used jQuery
All i did was add a class hide-nav to your nav with display none. And a button to click of course.
And a bit of jQuery
$(document).ready(function() {
$('#topMenu-btn').on('click', function() {
$('nav').slideToggle();
});
});
Try something like this:
http://jsfiddle.net/kb668aag/
You'll need to modify the code a bit.
<div id="topMenu"></div>
<nav>
<ul>
<li>Link</li>
<li class="has_children">Link
<ul class="sub-menu">
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
<li>Link 4</li>
<li>Link 5</li>
<li>Link 6</li>
<li>Link 7</li>
</ul>
</li>
<li class="has_children">Link
<ul class="sub-menu">
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
<li>Link 4</li>
<li>Link 5</li>
<li>Link 6</li>
<li>Link 7</li>
</ul>
</li>
<li class="has_children">Link
<ul class="sub-menu">
<li>Link 1</li>
<li>Link 2</li>
</ul>
</li>
<li>Link</li>
<li>Link</li>
<li>Link</li>
</ul>
</nav>
CSS
body {
padding: 0;
margin: 0;
}
#topMenu {
height: 50px;
width: 100%;
background-color: #cde;
display: block;
}
nav {
width: 100%;
height: auto;
display: block;
margin: 0;
padding: 0;
}
nav a {
text-decoration: none;
padding-left: 40px;
padding: 20px 40px;
display: block;
}
nav ul {
list-style: none;
display: block;
margin: 0;
padding: 0;
background-color: #ccc;
}
nav ul li {
display: block;
width: 100%;
border-top: 2px solid #abc;
}
nav ul ul {
overflow: hidden;
padding-top: 0px;
}
nav ul ul li a {
padding-left: 100px;
}
ul.sub-menu{
display: none;
}
.has_children > a{
color: #ddd;
}
JS:
var $menu_with_children = $('.has_children > a');
$menu_with_children.on('click', function(e){
e.preventDefault();
var $this = $(this);
if (!$this.parent().find('> .sub-menu').hasClass('visible')) {
$this.parent().find('> .sub-menu').addClass('visible').slideDown('slow');
} else{
$this.parent().find('> .sub-menu').removeClass('visible').slideUp('slow');
}
});