How to limit body height to viewport - css

I got a little problem with my recent attempt to learn about HTML and CSS.
Here is the ting: I got myself a HTML page which shows ~100 divs representing a list on the left side. However I want the parent div to contain a scrollbar but its length to be limited by the viewport.
The problem is, when I open the page, the whole body is streched to fit the full list which is not, what I want. Below is a pic with some sample data to show you because my english is not the best. The elements for the "sidebar" get generated by JavaScript and are just divs with text inside (I don`t know, if paragraphs would be better)
Snapshot from browser window
As you can see, the scrollbar is on the right border and when I scroll the whole body is scrolled. I would rather like to have a scrollbar within the "list" and just scroll this without moving the viewport around.
Here is my CSS:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
height: 100vh;
}
body {
display: flex;
flex-direction: column;
margin: 0;
}
/*--------------------
* Header
*------------------*/
header {
display: flex;
align-items: center;
height: 60px;
background-color: #4d4d4d;
}
header h1{
flex: 1;
color: white;
font-size: 24px;
font-family: Tahoma;
}
header ul {
display: flex;
flex: 1;
list-style-type: none;
height: 100%;
margin: 0;
}
header li {
flex: 1;
color: white;
text-align: center;
font-family: Tahoma;
font-size: 20px;
padding-top: 30%;
}
header li:hover {
background-color: #333333;
}
header img {
background-color: none;
height: 20px;
width: 20px;
}
/*--------------------
* Main area
*------------------*/
main {
flex: 1;
display: flex;
margin: 1%;
}
/*--------------------
* Sidebar
*------------------*/
#sidebar {
display: flex;
flex: 1;
overflow: auto;
}
#sidebar div {
flex: 1;
text-align: center;
}
#sidebar .th{
text-transform: capitalize;
}
/*--------------------
* Details
*------------------*/
#details {
flex: 4;
margin-left: inherit;
}
And here is my index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<ul>
<li id="btnPerson">Persons</li>
<li id="btnCompany">Companies</li>
<li id="btnSave">Save</li>
<li id="btnLoad">Load</li>
<li id="inpChoose">Choose file</li>
<li id="btnSearch"></li>
</ul>
</header>
<main>
<div id="sidebar"></div>
<div id="details"></div>
</main>
<script src="src/main.js"></script>
<script src="src/ui.js"></script>
<script src="src/init.js"></script>
</body>
</html>
Here is some code to reproduce my problem:
var sidebar = document.getElementById("sidebar");
var table = document.createElement("div");
table.className = "table";
sidebar.appendChild(table);
for (var i = 0; i < 50; i++) {
var e = document.createElement("div");
e.innerHTML = "blabla";
table.appendChild(e);
}
I hope some smart people can help me with this
Cheers
Mirodin

You should wrap your div id="details" inside another div work as a wrapper and use this css:
.wrapper{
overflow:scroll;
height:100px;}
Why not use table?

Related

Align list items under input box with flexbox

Im trying to align the ul lis under an input box and send the span element to the right of the input box
I read other threads and how to send the span to the left with justify-content: space-between; but that doesn't want to work too. Also tried to add margin to the list to push the text around but it doesn't feel right not to mention that I still cant figure out how to stick the delete span to the right. Here is my jsfiddle https://jsfiddle.net/h0w6yp1x/
.list { justify-content: space-between;}
.list li { justify-content: space-between;}
Define a wrapper div between li tags. And make it flexbox, then justify content of this wrapper div.
Like this:
<li>
<div class="li-wrapper"> Random Text1 <span class="btn-remove">delete</span></div>
</li>
Working code is below:
const DOM = {
input: document.querySelector('.user-input'),
list: document.querySelector('.list'),
btnAdd: document.querySelector('.btn-add'),
btnDelete: document.querySelector('.btn-remove')
}
let addItem = function() {
if (DOM.input.value === '') {
return;
} else {
const html = `<li> <div class="li-wrapper">${DOM.input.value} <span class="btn-remove">delete</span></div> </li>`;
DOM.list.insertAdjacentHTML('beforeend', html);
DOM.input.value = '';
}
};
let removeItem = function(element) {
element.parentNode.parentNode.removeChild(element.parentNode);
}
DOM.btnAdd.addEventListener('click', function() {
addItem();
});
DOM.list.addEventListener('click', function(e) {
let element = e.target;
if (e.target && e.target.matches("span.btn-remove")) {
removeItem(element);
}
})
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
html {
height: 100%;
}
body {
font-family: 'Roboto', sans-serif;
height: 100%;
background: #d53369;
/* fallback for old browsers */
background: -webkit-linear-gradient(to bottom right, #cbad6d, #d53369);
/* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to bottom right, #cbad6d, #d53369);
/* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
background-repeat: no-repeat;
background-attachment: fixed;
}
.container {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
margin: 100px auto;
width: 360px;
box-shadow: 0 0 3px rgba(0, 0, 0, 0.3)
}
.container h1 {
text-align: center;
}
.user-inerface {
display: flex;
justify-content: center;
align-items: center;
}
.user-input {
border: none;
padding: 5px;
}
.btn-add {
border: none;
padding: 5px;
}
.list {
border: 2px solid black;
width: 100%;
text-decoration: none;
list-style: none;
display: flex;
flex-direction: column;
line-height: 20px;
color: #9400D3;
}
.li-wrapper {
display: flex;
justify-content: space-between;
}
.list li:nth-child(2n+2) {
opacity: 0.8;
}
.list li:hover {
opacity: 0.7;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="https://fonts.googleapis.com/css?family=Roboto&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<title>Document</title>
</head>
<body>
<div class="container">
<h1>Todos</h1>
<div class="user-interface">
<input type="text" class="user-input" placeholder="New todo">
<button class="btn-add">Add</button>
</div>
<ul class="list">
<li>
<div class="li-wrapper"> Random Text1 <span class="btn-remove">delete</span></div>
</li>
<li>
<div class="li-wrapper"> Random Text1 <span class="btn-remove">delete</span></div>
</li>
<li>
<div class="li-wrapper"> Random Text1 <span class="btn-remove">delete</span></div>
</li>
<li>
<div class="li-wrapper"> Random Text1 <span class="btn-remove">delete</span></div>
</li>
</ul>
</div>
<script src="main.js"></script>
</body>
</html>
If you set the .list li selector to have display: flex then that appears to cause the items in the list box to show the text on one side and the delete on the other.

Elements overflowing viewport and causing horizontal scroll

I'm trying to do a static HTML & CSS webpage using flexbox but my conten doesn't fit into the window in Chrome browser. I can scroll horizontally, so I have more space horizontally than the browser window size.
This is an screenshot showing the problem. The margins are the same in the two sides of the wrapper, but the content is not fitted to 100% width of the browser window, so I can scroll horizontally, which is not what I want.
I've tried the same code in Safari and works perfectly. Is this an issue with flexbox in Chrome or what am I missing? Thanks.
This is my HTML:
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSS Stylesheets-->
<link rel="stylesheet" href="css/vendor/normalize.css">
<link rel="stylesheet" href="css/vendor/font-awesome.css">
<link rel="stylesheet" href="css/vendor/devicons.css">
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<!-- Header -->
<header>
<nav>
<ul>
<li>ELEMENT 1</li>
<li>ELEMENT 2</li>
<li>ELEMENT 3</li>
</ul>
</nav>
</header>
<!-- Main Content -->
<main>
<div class="main-wrapper">
<div class="search-bar">
<form>
<input type="text" placeholder="Search">
</form>
</div>
</div>
</main>
</body>
And this is my SCSS:
/* 2. HEADER */
nav {
width: 100%;
text-align: center;
background-color: $dark-grey;
& ul {
max-width: $width;
margin: auto;
display: flex;
}
& li {
flex: 1 1 0;
}
& a {
display: block;
color: $white-alpha;
padding: 30px 0px;
transition: color 0.3s ease;
}
& a:hover {
color: $white;
transition: color 0.3s ease;
}
& a.active {
color: $white;
}
}
/* 3. MAIN*/
main {
background-color: $light-grey;
padding: 30px 0px;
}
.main-wrapper {
max-width: $width;
margin: auto;
}
/* 3.1. SEARCH BAR */
.search-bar {
padding-bottom: 20px;
& input {
height: 45px;
width: 100%;
border-bottom: 1px solid $medium-grey;
border-radius: 2px;
text-indent: 20px;
}
}
As far as I can tell, your margins and box-model are likely the problem + you are using the & improperly.
You may also want to look into the default page margin and setting the box-model to border-box site wide.
https://www.paulirish.com/2012/box-sizing-border-box-ftw/
For questions like these, make a CodePen or jsFiddle etc, with only the bare bones of what is needed to recreate the situation you are having trouble with. http://codepen.io/sheriffderek/pen/e76eb24c23c789accffe6a18fcfdd8c0 - even my example has more style than needed...
One more suggestion - if you are new to flex-box, it really helped me to write out the individual properties like flex-grow flex-shrink flex-basis instead of the short-hand + always explicitly set the flex-direction or any other defaults.
html { // sort out box-model
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
body { // reset body margin default
margin: 0;
}
a {
text-decoration: none;
color: inherit;
}
html {
background: lightblue;
}
header, main {
padding: 1rem;
}
header {
background: white;
}
nav {
ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
#media (min-width: 500px) {
flex-direction: row;
}
}
li {
flex: 1 1 0;
}
a {
display: block;
padding: 1rem;
&:hover {
background: black;
color: white;
}
&.actiive {
color: red;
}
}
}
main {
background: gray;
}
.main-wrapper {
max-width: 960px;
margin: auto;
}
.search-bar {
//
input {
height: 45px;
width: 100%;
text-indent: 20px;
background: black;
color: white;
border: 1px solid black;
}
}

Unwanted Space Between <header> and <nav>

I have the following HTML5 code:
<!doctype html>
<html>
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
body {
max-width: 960px;
margin: 0 auto;
font-size: 120%;
}
header, nav {
margin: 0;
padding: 0;
border: 1px solid black;
}
header {
border-color: red;
}
img.mainpicture {
width: 100%;
height: auto;
}
</style>
</head>
<body>
<header>
<img class="mainpicture" src="http://s29.postimg.org/ajjbb0n07/apic.jpg" alt="A picture"/></header><nav>Navigation area.</nav>
</body>
</html>
Can someone please explain why there is about 5 pixels of empty space between the <header> and the <nav> content, and how can I remove it?
By adding
header {
padding-bottom: 1px;
}
to the CSS file, the height of the white space is extended by one pixel, so it doesn't seem to have anything to do with the padding of <header>.
EDIT: I would like to do it without using <nav style="position: relative; top:-7px;">.
Set display block on the image for fixing fitting issues.
body {
max-width: 960px;
margin: 0 auto;
font-size: 120%;
}
header,
nav {
margin: 0;
padding: 0;
border: 1px solid black;
}
img.mainpicture {
width: 100%;
display: block;
}
<header>
<img class="mainpicture" src="//lorempicsum.com/futurama/960/200/2" alt="A picture" />
</header>
<nav>
Navigation area.
</nav>
Just add
img.mainpicture{
.....................
.....................
vertical-align: top;
}
That will fix the issue:)
It could be because of the inner elements having a margin, that is protruding outside! And also since you have an <img />, give a display: block; to it. Try overflow: hidden; for both header, nav:
header, nav {
overflow: hidden;
}
header img {
display: block;
}
Set the property margin-bottom equal to zero.
margin-bottom: 0;

Click Drop Down Menu for Responsive layout

I am refining a responsive navigation menu, and would like to have the menu icon clicked to have the drop down menu instead of the hover effect. I am using a Google jquery so I am not sure if that is all ready scripted in the script src or not, and would I have to create the drop down menu manually in jquery or just an easy CSS or html5 fix. Thanks for any feedback.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Dan Meier Website</title>
<meta name="description" content="Responsive Header Nav">
<meta name="author" content="Treehouse">
<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1">
<link rel="stylesheet" href="layoutnew.css">
<!--[if IE]> <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
</head>
<body>
<header>
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Work</li>
<li>Blog</li>
<li>Contact</li>
</ul>
</nav>
</header>
CSS
header {
background: #404040;
width: 100%;
height: 76px;
position: fixed;
top: 0;
left: 0;
border-bottom: 4px solid #4C9CF1;
z-index: 100;
}
#logo{
margin: 20px;
float: left;
width: 200px;
height: 40px;
background: img src="images/menuicon.png" no-repeat center;
display: block;
}
nav {
float: right;
padding: 20px;
}
#nav ul.sub-nav {
display: none;
}
#nav ul.visible {
display: block;
}
ul {
list-style: none;
}
li {
display: inline-block;
float: left;
padding: 10px
}
/*MEDIA QUERY*/
#media only screen and (max-width : 640px) {
header {
position: absolute;
}
#menu-icon {
display:inline-block;
}
nav ul, nav:active ul {
display: none;
position: absolute;
padding: 20px;
background: #fff;
border: 5px solid #444;
right: 20px;
top: 60px;
width: 50%;
border-radius: 4px 0 4px 4px;
}
nav li {
text-align: center;
width: 100%;
padding: 10px 0;
margin: 0;
}
Use CSS to style and hide your menu and do the following:
Load jQuery (I can't see that in your code)
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
And you can do something like this (to show and hide the menu on click)
$('#menu-icon').click( function(){
$('nav ul').toggle();
});
$(window).resize(function(){
var w = $(window).width();
if(w > 320 && menu.is(':hidden')) {
menu.removeAttr('style');
}
});
Where "menu" is the variable value of your menu. you can declare it like.....
$(function() {
var menu = $('ul li');
});
hope it will help you..... :D
Rj

Make the BODY DIV Fill the Available Area

I'm working on a brand new website and I'm trying to just get the basic layout going. I am using the ASP.NET MVC 4 generated HTML and I would like to get the DIV named body to fill the available space after making room for the header and thus anchoring the footer to the bottom of the browser window. However, what I'm getting right now is three panels just stacked on top of each other.
I would like a solution that would work if the browser supported HTML5 and one if it didn't
Please note I've inlined comments in the CSS to try and explain what I've tried.
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title - Title</title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
#Styles.Render("~/Content/css")
</head>
<body>
<header>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title">#Html.ActionLink("Title", "Index", "Home")</p>
</div>
</div>
</header>
<div id="body">
#RenderSection("featured", required: false)
<section class="content-wrapper main-content clear-fix">
#RenderBody()
</section>
</div>
<footer>
<div class="content-wrapper">
<div class="float-left">
<p>© #DateTime.Now.Year - ACME. All rights reserved.</p>
</div>
<div class="float-right">
<ul id="social">
<li>Facebook</li>
<li>Twitter</li>
</ul>
</div>
</div>
</footer>
#RenderSection("scripts", required: false)
</body>
</html>
CSS
body {
/* I'VE TRIED BOTH OF THE FOLLOWING TO SEE IF THE BODY ITSELF WOULD SPAN */
/* WITH NO OTHER CSS APPLIED TO THE body ELEMENT */
/*height: fill-available;*/
/*height: 100%*/
}
/* general layout
----------------------------------------------------------*/
.float-left {
float: left;
}
.float-right {
float: right;
}
.clear-fix:after {
content: ".";
clear: both;
display: block;
height: 0;
visibility: hidden;
}
/* main layout
----------------------------------------------------------*/
.content-wrapper {
margin: 0 auto;
max-width: 960px;
}
#body {
background-color: #efeeef;
clear: both;
padding-bottom: 35px;
/* I'VE TRIED BOTH OF THE FOLLOWING TO SEE IF I COULD GET THIS ELEMENT TO SPAN */
/* WITHOUT ANY OTHER CSS APPLIED TO THE body TAG */
/*height: fill-available;*/
/*height: 100%*/
}
.main-content {
/*background: url("../Images/accent.png") no-repeat;*/
padding-left: 10px;
padding-top: 30px;
}
.featured + .main-content {
/*background: url("../Images/heroAccent.png") no-repeat;*/
}
footer {
clear: both;
background-color: #e2e2e2;
font-size: .8em;
height: 100px;
}
/* site title
----------------------------------------------------------*/
.site-title {
color: #c8c8c8;
font-family: Rockwell, Consolas, "Courier New", Courier, monospace;
font-size: 2.3em;
margin: 20px 0;
}
.site-title a, .site-title a:hover, .site-title a:active {
background: none;
color: #c8c8c8;
outline: none;
text-decoration: none;
}
/* social
----------------------------------------------------------*/
ul#social li {
display: inline;
list-style: none;
}
ul#social li a {
color: #999;
text-decoration: none;
}
a.facebook, a.twitter {
display: block;
float: left;
height: 24px;
padding-left: 17px;
text-indent: -9999px;
width: 16px;
}
a.facebook {
background: url("../Images/facebook.png") no-repeat;
}
a.twitter {
background: url("../Images/twitter.png") no-repeat;
}
Just snap the header and footer at the bottom of the page using fixed positioning.
header, footer{ position:fixed; left:0; right:0; z-index:1; }
header{ top:0; }
footer{ bottom:0; }
Then you can give your body the background your div#body had before. The div gets no background and will expand as much as needed.
div#body{ background:none; }
body{ background:#eee; }
This will look like the div would fill the remaining space of the page. Finally give your header and footer a background so that you can't see the background of the body under it.
header, footer{ background:#fff; }
By the way I would suggest removing body margins. body{ margin:0; }
I believe it's a bit impossible to do that with just CSS. You can make a webpage with 100% height like this:
html{
height: 100%;
}
body{
height: 100%;
}
#body{
height: 100%;
}
And then for header, body and footer you can do like this:
header{
height: 100px;
left: 0;
position: absolute;
top: 0;
width: 100%;
background-color: #f00;
}
#body{
bottom: 100px;
left: 0;
position: absolute;
right: 0;
top: 100px;
background-color: #fff;
}
footer{
bottom: 0;
height: 100px;
left: 0;
position: absolute;
width: 100%;
background-color: #ff0;
}
It might work for a bit, but it'll break at some point. When you resize your browser, it'll be running out of room for your #body. If you want a better solution, you should use javascript. In your javascript, calculate how much space you have for your #body, then either adjust the height of header and footer. Or adjust the #body instead.

Resources