Setting a max-height of page-height for a dropdown - javascript

Say you have a dropdown with a lot of options that overflow the page height. I know I can use overflow: auto to make it scroll, but only if I set it a max-height. How do I set a max-height that ensures the element won't overflow the browser window?
Like in this image
The left is what it's like now. Dropdown overflows page. The right is what it should be like -- the dropdown is resized to be height of just under the page height.
I've tried setting max-height to different values like 45vh since the dropdown is about halfway down the page, but this needs to fit all types of screen sizes so isn't flexible enough.
CSS solutions preferred in this case.

You can calculate the current distance between the dropdown and the bottom of the page (https://stackoverflow.com/a/7656176/5370933) and append styles with this value.
.myDropdown {
max-height: myDistance;
overflow: scroll
}
I think something like that could works. But you will have to use some JS to get the distance dynamically (depend on the user screen and/or user scroll before the dropdown opening...)

If I understood correctly the layout of your web page, the dropdown is the last element (well maybe) in the page.
What you could do is, first, add this lines to your main page container:
#page {
min-height: 100vh; /* Or the value you like most */
}
Now we have access to the full height of the document.
Next, you can simply use flexbox's space-between or space-around value to keep the dropdown on the bottom of the page (like footers).
But now, you want a little space between the end of the page and the dropdown. Simply add a margin-bottom and its done.
Now be aware that, I understand that there may be a footer or something below the dropdown. You can implement this solution in any container.
This isn't a bug-free solution, but it doesn't require javascript.
Here is a working example.
function _test_add(){
document.getElementById("dropdown").innerHTML += "<li>Item</li>";
}
#page {
min-height:100vh;
display:flex;
flex-direction: column;
justify-content: space-between;
}
#addbtn {
margin:0 auto;
}
/*
* Fictif Content
*/
#main-content {
height: 50vh;
display:flex;
justify-content:center;
align-items:center;
background-color:gray;
}
#dropdown {
min-height: 8em;
max-height: 18em;
background-color:#f1f1f1;
padding: 0;
list-style-type: none;
overflow: auto;
margin-bottom:4em;
border: solid black 2px;
}
#dropdown li {
padding:1em;
}
#dropdown li:nth-child(odd) {
background-color: #fafafa;
}
<div id="page">
<div id="main-content">
Main Content
</div>
<button id="addbtn" onclick="_test_add()">[TEST] Add items in dropdown</button>
<ul id="dropdown">
<li>Item</li>
<li>Item</li>
<li>Item</li>
</ul>
</div>

Related

Sticky sidebar not sticking in Vue.js

After way too much time agonizing over the breakage of a simple sticky sidebar component I've used without issue on numerous projects, I identified a partial solution that caused other issues.
This sidebar makes use of flexbox to keep the sidebar in place and treat a container div like the body of the page.
Unfortunately, it broke as soon as I started using it in Vue.js. I initially assumed it was because the element heights were not responding to dynamically populated content, but this is not the case.
The wrapper structure looks like so:
<html>
<body>
<div class="wrapper">
<div id="sidebar>
</div>
<div class="container">
</div>
</div>
</body>
</html>
And the CSS:
html {
position: relative;
height: 100%;
box-sizing: border-box;
width: 100%;
overflow-x: hidden;
height: 100%;
}
body {
overflow-x: hidden;
margin: 0;
min-height: 100%;
position: relative;
background-size: 100vw 100vh;
background-attachment: fixed !important;
width: 100%;
}
.wrapper {
display: flex;
align-items: stretch;
}
#sidebar {
height: 100vh;
position: sticky;
position: -webkit-sticky;
}
.container {
width: 100%;
margin-right: auto;
margin-left: auto;
}
NB: I did successfully cause the sidebar to look like it was sticking by setting the body height to 100%, but the actual links still scrolled, even though you could see the sidebar. Furthermore, this broke the layout properties of the Flatpickr datepicker being used on one of the most important pages in the site. Obviously, this is not a tenable solution, because a visible but interaction-less sidebar is useless, and I need my pages to actually work.
To be clear-- I chose to use sticky rather than fixed because I wanted to take advantage of flexbox to set the page content's container effectively next to the sidebar, rather than simply pushing it over using margin to keep it from being overlaid by the sidebar.
Here's a (messy, I apologize-- it's pulled out of a muuuuuuuch larger project) Codesandbox to show you the sidebar in context.
https://codesandbox.io/s/8897m88kl

Slide up a "fixed height div" that splits a web page horizontally?

I need a box that slides up from the bottom of my page. I will use the box to show important information to new users. So for example, immediately after signup, the box will slide up with a welcome message.
I've made this jsfiddle that to some extend exemplifies the desired behaviour. It's just a div that gets slided up from the bottom:
$('.foot').addClass('slide-up', 500, 'easeOutBounce');
However, the code is only to exemplify, because the implementation is insufficient for the following reasons:
The bottom box has a pre-determined 500px height, because it's initially hidden 500px below the browser. Instead, I need just the box height to fit its content. The content will vary, and will even be changed through javascript once loaded.
The bottom box emerges on top of other elements. Instead, I want to split the screen in 2. A bottom half that has as much height as the box content needs. And a top half that behaves just like a regular web page, i.e. if there is too much content the user can just scroll down. To exemplify the described effect you can check this jsfiddle (the code has no relevance though)
How could achieve the described behaviour?
After experimenting with several methods, I ended up with a solution that combines some ideas given in freedomm-n's comments (modify the size of the main div) and in Nikhil's answer (use a flex container). You can see the result in this jsfiddle.
For the following markup:
<div id="divContainer">
<div id="divTop">
Main content
</div>
<div id="divFooter">
Footer content
</div>
</div>
And these styles:
html, body, form
{
margin: 0;
padding: 0;
overflow: hidden;
height: 100%;
}
#divContainer
{
width: 100%;
height: 100%;
}
#divTop
{
overflow-y: auto;
padding: 8px;
height: calc(100vh - 16px); /* Accounts for padding and border (if any) */
}
#divFooter
{
padding: 12px;
text-align: center;
border: 1px solid black;
border-top-left-radius: 25px;
border-top-right-radius: 25px;
}
.containerEnd
{
display: flex;
flex-direction: column;
}
.topEnd
{
height: auto;
flex-grow: 1;
}
This Javascript code is used to animate the div elements:
function slideUpFooter() {
var currentHeight = $('#divTop').height();
var footerHeight = $('#divFooter').outerHeight(true);
$('#divTop').animate(
{ height: currentHeight - footerHeight },
2000,
'easeOutBounce',
function () {
$('#divContainer').addClass('containerEnd');
$('#divTop').addClass('topEnd');
});
};
The function called at the end of the animation sets the flexbox parameters, to ensure that the footer sticks to the bottom of the page.
I have updated your Fiddle. Look below for details.
You don't need to use position: fixed for the .foot section, you could use position: relative instead. Since I noticed you were using flex, I took the liberty to fix this using the same.
Changes made
Firstly I suggest adding a div container, giving a class name say - container.
Make the container display: flex & change the default direction to flex-direction: column.
Now since you want the main-content to be scroll-able depending on its contents, you need to first set a height to this section with height: 200px; and then make it scroll-able using overflow-y: auto;
Let me know if you have any doubts.

How can I make my tree view elements overflow past the parent div's width?

I am using bootstrap-treeview to try to make a nice treeview within my MVC project. This control is available on NuGet so its easy to get started with it. The left hand div shows the tree and the right hand div shows the content of each element when clicked:
<body>
<div id="tree" style="position:absolute; width: 20%; height: 100%; overflow: scroll"></div>
<div id="content" class="list-group-item node-tree" style="position: absolute; left: 20%; width: 80%; height: 100%">This is where content goes once you click on a file or folder element.</div>
</body>
There is a slight problem, though. The content of the div with the ID = tree gets cut off:
Ideally, I would like these list elements to overflow to the right, beyond the size of the div with the ID = tree, as you can tell, because I have set overflow: scroll, so I do not want any text to wrap to a new line.
On runtime, it appends list elements as follows...
These list elements seem to have the following CSS:
.list-group-item {
position: relative;
display: block;
padding: 10px 15px;
margin-bottom: -1px;
background-color: #fff;
border: 1px solid #ddd;
}
I have tried adding white-space: nowrap; to this CSS, which makes the text do what I want (and overflow with a scrollbar), but the background and border of each list element stay at the width of the parent (which is not what I want; I want them to also overflow all scrollable width just like I did with the text)!
What can I do to make each element of this list properly overflow past the bounds of the parent div they all exist under?
Edit: I've tried putting overflow:visible on all parent levels as well, but it did not work. It removed the vertical scroll bar and kept all list item background borders still restricted to the width of the tree div. I also found that setting width = 10000px on the .list-group-item CSS partially gives me what I want as well, but obviously this makes the backgrounds too wide and the scroll bar becomes too elongated. I want the width of all list elements to be equal to the width of the widest overflowing content.
I figured it out. I had to change the display to table-row-group and I had to add white-space: nowrap:
.list-group-item {
position: relative;
display: table-row-group;
padding: 10px 15px;
margin-bottom: -1px;
background-color: #fff;
border: 1px solid #ddd;
white-space: nowrap;
}
Add overflow:visible to the parent element(s). You may need this at multiple levels, as each parent element could potentially restrict the content.

Single window application with 100% height and no scrollbars

I am currently developing a web application using jQuery.
The layout for the same goes as shown in the figure given below:
The orange color box at the very back should be 100% in height and width with some margin like 5px or so.
The logo and the tab-bar are placed as shown and are about 50px in height. But tab-bar should take size as shown with some margin.
The tab content should occupy the remaining height and should scroll for the contents it occupies.
Similar structure is required for the internal menubar and tab content.
Can anyone please suggest the layout method to employ?
Or how can I manipulate different heights/widths?
The requirement also suggests a responsive window i.e. the width/height to manipulate on resize.
The jsFiddle I said I'd make.
As you'll see, I make use of jQueryUI for the "tabs" layout and simply "add" a few things. The few things I "Add" are simple and the jQueryUI alreqady provides a strong CSS with which to manipulate to get desired result. Also attached to that page is a theme-switcher, so you could see what it would look like using different jQueryUI Default Themes.
I'll try to explain the process as shortly as possible without being to vague.
HTML
I first start with a basic page wrapper. Not too necessary, but it provides a nice "element" with which to work inside of and possibly make manipulations for page layout change in otherways in the future. For now it simply holds our page "padding" of 5px. The HTML and BODY tags will be set to a default and should not be manipulated beyond that as height and other properties begin to take different meanings for these tags in different browsers.
I then place 2 divs inside this wrapper, again, these could be done without depending on your needs. I like these 2 divs and use this alot because it provides "vertical align -> middle" as one might expect. The first, parent, is a div with class table. This will have its display set to table to provide a "table-like" layout but still have the ability to do things like "round the corners" or, as in my case, set height! The second, child, is the same except it will have a class and style as table-cell, respectively. This allows us to set something like vertical-align: middle; and ensure that this element is in the vertical middle of the page/table element. Again, with your layout, this may seem unneccessary, but I don't know your full expected end result and I'm trying to give as much "fluid dynamics" to the page as possible.
Finally, I first insert the jQueryUI tabs HTML in their expected layout, with 2 small differences. I place our "logo" in a custom span tag just before the ul. I also take the ui-tab-panel(s) and place them in their own container. This helps us adjust the height of our tabs area as needed. I also gave this container overflow, so even tho overflow maybe hidden on the body, it's still available for the tabs. (see also: small blog i wrote on jQueryUI Tabs)
<div class="page-wrapper">
<div class="table">
<div class="table-cell">
<div id="tabs">
<span class="my-logo">
<img src="http://www.w3.org/html/logo/downloads/HTML5_Logo_512.png" alt="logo here" />
</span>
<ul>
<li>Nunc tincidunt</li>
<li>Proin dolor</li>
<li>Aenean lacinia</li>
</ul>
<div class="ui-tabs-panel-container">
<div id="tabs-1">
<<p> ... </p>
</div>
<div id="tabs-2">
<p> ... </p>
</div>
<div id="tabs-3">
<p> ... </p>
</div>
</div>
</div>
</div>
</div>
</div>
CSS
As I mentioned before, jQueryUI provides us with a strong CSS to work with already. As you might have noticed, I made use of some of this by using their predefined class names throughout the HTML. This established things like background, color, and even font-family and more! Now that that is over with, let's layout our page mechanics first. As I mentioned, I give a very "direct" set of properties to HTML and BODY. This will help eliminate "Cross-browser-issues". I also provided a background color, tho you could set that at one of the children levels. This was done just to show you where HTML, BODY exist.
I then set our "frame" elements. .page-wrapper will provide our page wrapping, sizing will come from within, so there is no need to deal with it here. The .table and .table-cell provide display exactly as their name suggest. As previously mentioned, this provides a nice ability to maintain an element in the exact "center" of something, even vertically!
Now we manipulate our tabs and content. I use #tabs throughout to maintain "name-spacing". This will not only help with any "css overrides" on jQueryUI presets, but also helps keep page layout confusions to a minimum. This is always a good thing.
The first thing I manipulate is the placement and setting of our custom span for the logo. Then, of course, I have to change the ul to next to it. Thus I look at the CSS for the uls class. If I open edit tools in a browser, I can see the ul is given the classname ui-tabs-nav and I can see it has a margin setting. If I play with the margin-left of this ul I can see that nothing is affected but the left side of the ul. PERFECT! Here is what I must manipulate to set our log in its "own space".
Finally, I simply set our tabs container (given custom class name, ui-tabs-panel-container, made to match jQueryUI) to have overflow, so that if any content exceeds our page height, it can still be scrolled within this element.
html, body {
background-color: #ADDFFF;
height: 100%;
padding: 0;
margin: 0;
overflow: hidden;
width: 100%;
}
.page-wrapper {
padding: 5px;
}
.table { display: table; }
.table-cell { display: table-cell; vertical-align: middle; }
#tabs .my-logo {
display: inline-block;
float: left;
height: 2em;
margin: .5em 0 0;
padding: 0;
width: 2em;
}
#tabs .my-logo img {
max-height: 100%;
max-width: 100%;
float: left;
}
#tabs .ui-tabs-nav {
margin-left: 2em;
}
#tabs .ui-tabs-panel-container {
overflow: auto;
}
JS
Finally, the easy work. I write a function to set the height of our tabs content area, since it will be "filling" the rest of the page. This take a little thought, but not hard to figure out. With the function written, I simply add it to the window resize event and call that event right after. This way it's resized on load, thus giving us our "end height" for first view. I also establish the tabs, although not much work there since I'm just making "default tabs". Feel free to experiment, go wild!
// the following will resize our tabs content area and account for all the spacing neccessary
function setContentHeight(e) { return $(window).innerHeight() - $(this).offset().top - 10; } // -10 to account for padding
$(function() { // our on page load call
$("#tabs").tabs(); // establish tabs
// add ability to resize tabs content area on window resize, then call resize event
$(window).resize(function(e) { $("#tabs .ui-tabs-panel-container").height(setContentHeight) }).resize();
})
As for the layout of tab content, it's all up to you and your imagination. Hopefully this will give you a good idea of where to get started though! Good luck!
You could use something like Blueprint CSS:
http://www.blueprintcss.org/
Here's a very quick and dirty layout (not using blueprint CSS, just plain CSS), as a general guideline. It still needs work, but it could be used as a starting point:
<html>
<head>
<style>
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden; /* hide page scrollbars */
}
div {
margin: 0 auto;
padding: 0;
border: 1px solid black; /* for debugging */
text-align: center;
}
#header {
width: 100%;
position: relative;
overflow: auto;
}
#header > div {
height: 5%;
float: left;
}
#logo {
width: 23%;
}
#spacer {
width: 1%; /* -1% for borders */
}
#tabbar {
width: 75%;
}
#tabContent {
}
#tabContent > div {
width: 100%;
}
#tabContentMenuBar {
height: 5%;
}
#tabContentMain {
min-height: 80%;
}
</style>
</head>
<body>
<div id="header">
<div id="logo">Logo</div>
<div id="spacer"></div>
<div id="tabbar" class="fullWidth">Tab bar</div>
</div>
<div id="tabContent">
Tab content
<div id="tabContentMenuBar">Tab content - menu bar</div>
<div id="tabContentMain">Tab content - main content</div>
</div>
</body>
</html>

How is this done? (JavaScript or else?)

I somehow found this webpage and was absolutely stunned by the navigation bar. www.webdesignerwall.com
When you put your mouse over "Home", "About" or "Jobs" menu options, you get that awesome rollover effect in the brown field above. I like that very much and had a similar idea, but being an amateur, I can't really say what type of programming is that. I would say it uses Ajax or JavaScript per se, but I'd like some of you to explain it to me, or even share some similar examples.
Thank you
This is done by CSS. It places an extra <span> into every <a> link element. With CSS <span>s are hidden and positioned correctly above the menu elements (absolute). When one of the link is hovered the new style applies to the correct <span> which makes it visible.
HTML
<ul id="nav">
<li id="nav-home"><a href="/>Home<span></span></a></li>
<li id="nav-about">About<span></span></li>
<li id="nav-jobs">Jobs<span></span></li>
</ul>
CSS
#nav span {
display: none; /* hidden by default */
position: absolute;
}
#nav a:hover span { /* link:hover */
display: block; /* makes one of them visible */
}
#nav-home span {
background: url(images/home-over.gif) no-repeat;
width: 168px; /* each has it's own image */
height: 29px; /* dimensions */
top: -30px; /* and coordinates */
left: 35px;
}
#nav-about span {
background: url(images/about-over.gif) no-repeat;
width: 157px;
height: 36px;
top: -36px;
left: 90px;
}
/* ... */
This effect can also be accomplished with CSS without JavaScript:
CSS Image rollovers
It's just CSS.
Each link has an id attribute, and each id has its own CSS rule which changes the background of the nav bar on hover.

Categories