I have a text-image component, and i need to vertical-align text middle to the floated image , if the text is less (condition one) (for larger screens). if the text is more then let it wrap around the floated image (condition two) (again for larger screens). How can i do this in CSS or do we need Javascript for this? Here is fiddle. Both my conditions one and two should work.
.clearfix { clear: both; }
.text-img { padding-left: 15px; padding-right: 15px; }
.text-img .info-box .info--body p { max-width: none; }
.text-img .info-box { text-align: justify; }
.text-img .stock-img { width: 100%; }
#media (min-width: 992px) {
.text-img.text-right .stock-img { width: 50%; float: left; }
.text-img.text-right .stock-img { padding-right: 15px; padding-bottom: 15px; }
.text-img.text-left .stock-img { width: 50%; float: right; }
.text-img.text-left .stock-img { padding-left: 15px; padding-bottom: 15px; }
}
<div class="clearfix text-img text-left">
<img src="https://cdn0.vox-cdn.com/thumbor/gvDQZLtlEM7U99rmTEdMoUtLRJU=/0x96:2039x1243/1600x900/cdn0.vox-cdn.com/uploads/chorus_image/image/50319283/ipad1_2040.0.0.jpg" alt="iPad" class="img-responsive stock-img" />
<div class="info-box">
<header class="info--header">
<h3 class="h3">The science of today is the technology of tomorrow.</h3>
</header>
<div class="info--body">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc semper urna nec lectus malesuada tincidunt. Aenean faucibus, nulla sed luctus tempus, purus libero vestibulum velit, et blandit odio nunc ac quam. Donec tellus tellus, venenatis ac diam nec, sodales viverra orci.</p>
</div>
</div>
</div>
I want the final output to be like this, which satisfys both my condition:
Well the answers given are right, this cannot be solved just by CSS alone, so i had to come up with jQuery solution. For those looking for solution for such scenarios, here is jQuery code that solved my problem:
$(document).ready(function() {
$(".text-img").each( function() {
var cH = parseInt( $( this ).height() );
var tH = parseInt( $( this ).find('.info-box').height() );
if( tH < cH ) {
var pt = ( cH - tH ) / 2;
$( this ).find('.info-box').css({
"padding-top" : pt + "px"
});
}
});
});
Use a flex box layout when you are in the smaller screens.
#media (min-width: 992px) {
.text-left {
display: flex;
align-items: center;
justify-content: center;
}
.text-left img {
max-width: 50%;
height: auto;
margin-right: 10px;
}
}
Preview
Output: http://jsbin.com/lulecudaji/edit?html,css,output
I would recommend you better/older than flex-box tick for centring elements.
For horizontal centring use simply text-align: center; on container div
For vertical centring uses propoerty of display inline-block elements which aligned in to the middle to center all display inline-block in the line.
Making it bigger i'll move other elements to the center
Making it 100% height causes the othere elements centers to the middle.
You simply need to create ghost (not visible) - red element to center content - blue and green elements.
For ghost element use for it before or after of conteiner div:
.continer:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
}
And display inline-block your content:
.content{
display: inline-block;
}
Of course delete position:absolute etc.
Last tweak will be to get rid of that small spaces between elements (especially between red and others) use one of the tricks from here: https://css-tricks.com/fighting-the-space-between-inline-block-elements/
Probably you will need to set font size to zero.
More about ghost elements:
https://css-tricks.com/centering-in-the-unknown/
Related
I am building a reactJS application in which the navbar is present only in middle column. But when I switch to mobile view, due to bootstrap by default the navbar comes below the first column. If I try to change the position to fixed-top it extends to all columns. I need it to stay in the middle in both lg and md views, but in small screens it should come above the first column. I have attached a screenshot.
This is the application in desktop view
This is in mobile view
How can I make this change in my website ??
You need to implement a combination of css, media breakpoints, and some pure JS. Here's a working example.
Switch the nav to position: fixed; at the mobile breakpoint, which I assume is 768.
Because fixed will remove it from the regular HTML element flow and place it overtop of other items, to account for that shift, add margin-top to the first container .element-one that is the same height as the nav + a few extra pixels to account for spacing.
var navBreakpoint = 768,
el1 = document.body.querySelector('.element-one');
navHeight();
window.addEventListener('resize', function(){
navHeight();
});
function navHeight(){
var mt = document.body.querySelector('nav').offsetHeight + 10,
docWidth = document.body.clientWidth;
if( docWidth < navBreakpoint ){
el1.style.marginTop = mt+'px';
} else {
el1.style.marginTop = 'unset';
}
}
.container {
display: flex;
position: relative;
}
.container > div {
padding: 1rem;
margin: 3px;
border: 1px solid #efefef;
}
.container nav {
position: relative;
border: 1px solid #efefef;
background: #efefef;
}
#media(max-width: 768px){
.container {
flex-direction: column;
}
.container nav {
position: fixed;
top: 0;
width: 100%;
height: auto;
left: 0;
padding: 0.5rem;
}
.element-one {
padding-top: 3rem;
}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="element-one">
Logo
</div>
<div class="element-two">
<nav>I AM THE NAV</nav>
Mi quis hendrerit dolor magna eget est lorem ipsum dolor. Tempor orci eu lobortis elementum nibh tellus molestie. Nulla facilisi morbi tempus iaculis urna.
</div>
<div class="element-three">
A condimentum vitae sapien pellentesque habitant morbi tristique senectus. Eget mauris pharetra et ultrices neque ornare. Lorem mollis aliquam ut porttitor.
</div>
</div>
I am trying to make a section where there are 2 cards, each one with a button and a small descriptive text.
What I am trying to achieve is that when I click on the button 3 things happen:
1 The button changes content, that goes from a "+" to a "-", but that is what worries me the least.
2 that a div is displayed with information corresponding to that card and that occupies 100 vw
and
3 that if there is a div displayed and the other button on another card is clicked, the first div disappears and the second appears and occupies the 100vw
-----What am I using? I am using HTML5, CSS, Vanilla Js, Bootstrap (mainly for the css)-----
This is what I want to achieve:
This is what I have achieved:
var jsaccordion = {
init : function (target) {
var headers = document.querySelectorAll("#" + target + " .accordion-btn");
if (headers.length > 0) { for (var head of headers) {
head.addEventListener("click", jsaccordion.select);
}}
},
select : function () {
this.classList.toggle("open");
}
};
window.addEventListener('load', function(){
jsaccordion.init("accordion-container");
});
.accordion-text {
display: none;
color: #808080;
padding: 15px;
border: 1px solid #ffcc4b;
}
.accordion-btn.open + .accordion-text{
display: block;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class='row'>
<div id="accordion-container" class='col-6'>
<div class="my-3">
<h3 class=" text-center">First one</h3>
<button class='mx-auto d-block accordion-btn btn btn-white border-primary'>+</button>
<div class="accordion-text">
<p>
some specific and special information for the first div.</p>
</div>
</div>
</div>
<div id="accordion-container" class='col-6'>
<div class="my-3">
<h3 class='text-center'>second one</h3>
<button class='mx-auto d-block accordion-btn btn btn-white border-primary'>+</button>
<div class="accordion-text">
<p>some specific and special information for the second div.</p>
</div>
</div>
</div>
</div>
Please help me, I don't know how to do it
It is a lot easier to do this in jQuery, but here is how I would approach it using Vanilla JS.
The idea is that to center something that is based on neither elements, but moreso the browser window, is to use a shared container (outside of either element) to print to. This takes the guess work out of positioning as well.
On clicking the button, the information should be copied from the accordion, and printed to the target container. Also on that click, check if the other is active to remove the active class. Adding classes to the active container to change the button symbol + and -, using CSS pseudo-elements.
Keeping the arrows inside the accordion containers will also make it easier to position them according to the HTML element it is in.
Sidenote: You should only use an HTML ID once on the entire page, otherwise use a class for multiple instances. This is in reference to #accordion-container.
var sharedCont = document.getElementById('shared-container');
var allCont = document.querySelectorAll('#accordion-container');
var jsaccordion = {
init : function (target) {
var headers = document.querySelectorAll("#" + target + " .accordion-btn");
if (headers.length > 0) { for (var head of headers) {
head.addEventListener("click", jsaccordion.select);
}}
},
select : function () {
var targ1 = this.parentElement.closest('#accordion-container'), // find parent
targText = targ1.querySelector('.accordion-text').innerHTML; // grab text for shared container
if( targ1.classList.contains('active') ){
// when clicked, if active, reset them all
targ1.classList.remove('active');
sharedCont.innerHTML = '';
sharedCont.classList.remove('active');
} else {
// when clicked, reset them all, then activate
for (let i = 0; i < allCont.length; i++) {
var el = allCont[i];
el.classList.remove('active');
}
targ1.classList.add('active');
sharedCont.innerHTML = targText;
sharedCont.classList.add('active');
}
}
};
window.addEventListener('load', function(){
jsaccordion.init("accordion-container");
});
body {
max-width: 90%;
margin: 0 auto;
overflow: hidden;
}
#accordion-container {
position: relative;
}
#accordion-container button::before {
content: '+' !important;
}
#accordion-container.active button::before {
content: '-' !important;
}
#accordion-container.active::after {
content: '';
width: 0;
height: 0;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-bottom: 15px solid orange;
position: absolute;
bottom: -2rem;
left: 50%;
transform: translateX(-50%);
color: orange;
z-index: 100;
font-size: 3rem;
line-height: 1;
}
#accordion-container .accordion-text {
display: none;
color: #808080;
padding: 15px;
border: 1px solid #ffcc4b;
}
/* .accordion-btn.open + .accordion-text{
display: block;
} */
#shared-container {
margin-top: 2rem;
display: block;
width: 100%;
padding: 2rem;
border: 1px solid orange;
display: none;
}
#shared-container.active {
display: block;
text-align: center;
}
#shared-container p {
margin: 0;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Testing testing testing</h1>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet"/>
<div class='row'>
<div id="accordion-container" class='col-6'>
<div class="my-3">
<h3 class=" text-center">First one</h3>
<button class='mx-auto d-block accordion-btn btn btn-white border-primary'></button>
<div class="accordion-text">
<p>Egestas erat imperdiet sed euismod nisi porta. Ipsum dolor sit amet consectetur adipiscing. Maecenas pharetra convallis posuere morbi leo urna molestie. Nullam vehicula ipsum a arcu. Gravida cum sociis natoque penatibus et magnis. Duis convallis convallis tellus id interdum velit laoreet. </p>
</div>
</div>
</div>
<div id="accordion-container" class='col-6'>
<div class="my-3">
<h3 class='text-center'>second one</h3>
<button class='mx-auto d-block accordion-btn btn btn-white border-primary'></button>
<div class="accordion-text">
<p>Tempus egestas sed sed risus pretium quam vulputate dignissim. Risus at ultrices mi tempus imperdiet. Mauris pellentesque pulvinar pellentesque habitant morbi tristique senectus et. Nisl vel pretium lectus quam id leo.</p>
</div>
</div>
</div>
</div>
<div id="shared-container"></div>
</body>
</html>
Its very simple you can assign id or class to those div, you want to hide or show then use javascript or jquery method to show and hide on the specific event click.
A small snippet of working example. It can be optimized and made dynamic.
Also as Owais suggested, we can simply use .show() and .hide() instead of .addClass() and .removeClass()
var firstDiv = $("#div-1-1");
var secondDiv = $("#div-1-2");
$(document).ready(function() {
//On Click of 1st Div, we're also toggling the 2nd DIV in case if it was open
// Can handle in a better way as well
// Same goes for the 2nd div
firstDiv.click(() => {
$(".dc-11").addClass("open");
$(".dc-12").removeClass("open");
});
secondDiv.click(() => {
$(".dc-12").addClass("open");
$(".dc-11").removeClass("open");
});
});
.outer-block {
width: 200px;
margin: auto;
}
.block {
display: flex;
}
.block>div {
flex: 1;
text-align: center;
border: 2px solid red;
height: 80px;
}
.open {
display: block !important;
}
.dc-11 {
background: red;
display: none;
}
.dc-12 {
background: orange;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<div class='outer-block'>
<div class="block">
<div>
<p>First</p>
<button id="div-1-1">+</button>
</div>
<div>
<p>Second</p>
<button id="div-1-2">+</button>
</div>
</div>
<div id="div-1-1-content" class="dc-11">First Div Content will be displayed here</div>
<div id="div-1-2-content" class="dc-12">Second Div Content will be displayed here</div>
</div>
</div>
There are N cards of the same class, each with a different amount of text inside. All cards are in the same flex container (row, wrap). In some cards part of the text is hidden because it exceeds the dimension limits for the class. I want such cards to expand and show the entire content on mouse hover. So far I can make it either to overlay the text only (as in the image) or to expand while moving the neighbors. Instead, such card should overlay above neighbor cards without moving them.
Ideally, the hovered card should expand both horizontally (if possible, symmetrically, otherwise to the left or to the right only), and vertically downwards.
Here is a very simple example created for this question. Each card contains a random length substring of lorem ipsum.
JavaScript, generates cards with random amount of text:
'use strict';
const lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ac auctor augue mauris augue neque gravida in fermentum et. Accumsan in nisl nisi scelerisque. Sed pulvinar proin gravida hendrerit lectus. Tortor id aliquet lectus proin nibh nisl condimentum. Erat pellentesque adipiscing commodo elit at imperdiet dui accumsan sit.';
const items = Array(30).fill(0)
.map(() => Math.ceil(lorem.length * Math.random()))
.map(idx => lorem.substring(0, idx))
.map(txt => `<div class="lorem-card">${txt}</div>`)
.join('');
const html = `<div class="cards-container">${items}</div>`;
document.body.innerHTML += html;
html is a skeleton only because the content is generated by JavaScript
<html>
<head>
<meta charset="utf-8">
<title>Cards demo</title>
<link rel="stylesheet" type="text/css" href="./cards.css">
</head>
<body>
</body>
<script src="./gen.js"></script>
</html>
And here is current CSS:
.cards-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: flex-start;
align-content: space-between;
}
.lorem-card {
flex-grow: 1;
background-color: white;
border: 3px solid #008CBA;
padding: 15px;
margin: 15px;
max-width: 150px;
max-height: 200px;
overflow: hidden;
opacity: 1;
}
.lorem-card:hover {
flex-grow: 10;
height: auto;
width: auto;
overflow: visible;
border: 3px solid red;
z-index: 100;
}
https://jsfiddle.net/fpmuc5Lz/3/
So far, this is what I have concluded: it is impossible to not cause the other divs to move while overlaying an element with an initially not absolutely positioned element. As a result, I've decided to create a copy element that is absolutely positioned that has exactly the same width of the original element. This is what I changed in your JS:
'use strict';
const lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ac auctor augue mauris augue neque gravida in fermentum et. Accumsan in nisl nisi scelerisque. Sed pulvinar proin gravida hendrerit lectus.';
const items = Array(30).fill(0)
.map(() => Math.ceil(lorem.length * Math.random()))
.map(idx => lorem.substring(0, idx))
.map(txt => `<div class="lorem-card"><div class="lorem-card--real">${txt}</div><div class="lorem-card--substitute">${txt}</div></div>`)
.join('');
const html = `<div class="cards-container">${items}</div>`;
document.body.innerHTML += html;
And your CSS:
.lorem-card {
position: relative;
flex-grow: 1;
max-width: 150px;
max-height: 200px;
margin: 15px;
overflow: hidden;
}
.lorem-card--real {
max-width: 150px;
max-height: 200px;
padding: 15px;
border: 3px solid #008CBA;
background: #FFF;
text-overflow: ellipsis;
}
.lorem-card--substitute {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
padding: 15px;
background: #FFF;
border: 3px solid #008CBA;
}
.lorem-card:hover {
overflow: visible;
}
.lorem-card:hover .lorem-card--real {
opacity: 0;
}
.lorem-card:hover .lorem-card--substitute{
height: auto;
overflow: visible;
border: 3px solid red;
z-index: 100;
}
The idea is to create a container for two Lorem cards. One that has a set width and height (200px and 150px at maximum) and one that can expand dynamically and overlay other elements without causing other divs to move (by using position: absolute). As can be seen, the effect is that the absolutely positioned element only expands vertically downwards. Furthermore, as height is set to auto, CSS transition does not work, which leads to the following suggestion.
My current idea, if you want it to expand both horizontally both ways and vertically downwards, is to compute the total width of the overall string (arranged in one horizontal line) and the height the largest character. Then, use some math to constraint the div's width and height ratio to 4:3 (while handling edge cases, e.g. specifying min-width and min-height) until you find an area that fits the whole text. This will allow you to have the exact width and height needed and as you can specify the exact width and height, you can also use CSS transition to smoothly expand the div.
Here is the new code: here
EDIT
After fiddling some more, here's the final code. In summary, what I added:
A dummy function that you can configure to decide how much the div should expand
Detection of whether an div needs to expand based on its TextNode's bounding rectangle
A smooth transition (the timeout logic has not been tested with edge cases)
Here's the full-working example:
'use strict';
const lorem = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ac auctor augue mauris augue neque gravida in fermentum et. Accumsan in nisl nisi scelerisque. Sed pulvinar proin gravida hendrerit lectus.';
const items = Array(30).fill(0)
.map(() => Math.ceil(lorem.length * Math.random()))
.map(idx => lorem.substring(0, idx))
.map(txt => `<div class="lorem-card"><div class="lorem-card--real">${txt}</div><div class="lorem-card--substitute">${txt}</div></div>`)
.join('');
const html = `<div class="cards-container">${items}</div>`;
document.body.innerHTML += html;
function getTextWidthAndHeight() {
return [210, 280]
}
let cards = document.querySelectorAll('.lorem-card')
let resetCardOverflow
for (let card of cards) {
card.addEventListener('mouseover', e => {
clearTimeout(resetCardOverflow)
card.style.overflow = 'visible'
// Configure "getTextWidthAndHeight" to fit the new rectangle size needs
let size = getTextWidthAndHeight()
let targetReal = card.querySelector('.lorem-card--real')
let targetSubstitute = card.querySelector('.lorem-card--substitute')
let textNode
for (let child of targetReal.childNodes) {
if (child.nodeName == '#text') {
textNode = child
break
}
}
// Get "height" of textNode's bounding box
let textHeight = 0;
let range = document.createRange();
range.selectNodeContents(textNode);
if (range.getBoundingClientRect) {
var rect = range.getBoundingClientRect();
if (rect) {
textHeight = rect.bottom - rect.top;
}
}
// If text exceeds box height (padding considered)
if (textHeight > 200 - 30) {
targetSubstitute.style.width = `${size[0]}px`
targetSubstitute.style.height = `${size[1]}px`
targetSubstitute.style.transform = `translateX(-30px)`
}
})
card.addEventListener('mouseleave', e => {
let targetSubstitute = card.querySelector('.lorem-card--substitute')
targetSubstitute.style.width = ''
targetSubstitute.style.height = ''
targetSubstitute.style.transform = ''
resetCardOverflow = setTimeout(() => {
card.style.overflow = ''
}, 200)
})
}
* {
box-sizing: border-box;
}
.cards-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: flex-start;
align-content: space-between;
}
.lorem-card {
position: relative;
flex-grow: 1;
max-width: 150px;
max-height: 200px;
margin: 15px;
overflow: hidden;
}
.lorem-card--real {
max-width: 150px;
max-height: 200px;
padding: 15px;
border: 3px solid #008CBA;
background: #FFF;
overflow: hidden;
}
.lorem-card--substitute {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
padding: 15px;
background: #FFF;
border: 3px solid #008CBA;
transition: all .2s ease;
overflow: hidden;
}
.lorem-card:hover .lorem-card--real {
opacity: 0;
}
.lorem-card:hover .lorem-card--substitute{
border: 3px solid red;
z-index: 1000;
}
<html>
<head>
<meta charset="utf-8">
<title>Cards demo</title>
<link rel="stylesheet" type="text/css" href="./cards.css">
</head>
<body>
</body>
<script src="./gen.js"></script>
</html>
In case you need the JS fiddle code: here
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
[I can't use JQuery, if you wanted to know.]
I'm trying to make my Menu come up and down. (Duh) I don't know how else to explain it, I want so if you put your cursor near the top of the screen, the menu will slide down from the top, (like an animation), and it will go back up when you move your cursor away from the top of the screen.
Code:
body {
background-color: #eeeeee;
}
Rounded {
padding: 17px 17px;
padding-top: 50px;
background: #dddddd;
border-radius: 25px;
}
Header {
font-style: arial;
font-size: 20px;
font-weight: 3px;
font-size-adjust: bottom;
color: #ededed;
}
Black {
color: 000000;
}
Backer {
}
Bod {
padding 15px 15px;
padding-left: 150px;
}
<html>
<head>
<title>Games-rade</title>
<link rel="stylesheet" href="CSS/Style.css">
<script src="Javascript/Java.js"></script>
</head>
<body>
<center>
<header>
<rounded><Black>---------------------------------- </Black>Main<text> | </text>About<text> | </text>Buy <Black>---------------------------------- </Black></rounded>
</header>
</center>
<br>
<br>
<br>
<Bod>
<h3> Hello. </h3>
</Bod>
</body>
</html>
Any Suggestions?
You can use CSS transitions on block elements to move your header in and out of view.
Below is a rough example using most of your code.
As an aside, you should really avoid using non-standard html elements (such as rounded) while learning; instead, add classes to standard elements. One last note, from looking at some of your CSS rules, I would recommend looking into the difference between display types, specifically block and inline, and what styles you can apply to each.
A good intro can be found here: http://learnlayout.com/display.html
body {
padding:0;
margin:0;
}
rounded {
padding: 17px;
background: #dddddd;
border-bottom-left-radius: 17px;
border-bottom-right-radius: 17px;
}
header{
font-size: 20px;
color: #ededed;
display:inline-block;
}
header rounded {
display:block;
transform:translateY(-100%);
transition:transform .5s ease;
}
header:hover rounded {
transform:none;
}
Black {
color: #000000;
}
Bod {
display:block;
padding 15px 15px;
padding-left: 150px;
}
<title>Games-rade</title>
<link rel="stylesheet" href="CSS/Style.css">
<script src="Javascript/Java.js"></script>
</head>
<body>
<center>
<header>
<rounded><Black>---------------------------------- </Black>Main<text> | </text>About<text> | </text>Buy <Black>---------------------------------- </Black></rounded>
</header>
</center>
<br>
<br>
<br>
<Bod>
<h3> Hello. </h3>
</Bod>
I did a simple example to you using jquery:
(function(){
var top_menu = $(".animation");
$(".menu").on("mouseenter", function(){
top_menu.slideDown();
});
$(".menu").on("mouseleave", function(){
top_menu.slideUp();
});
})();
Hope it helps.
I'm not too familiar with the language myself but Codecademy has a tutorial on making interactive webpages and I believe it covers just this. Plus, it's a good way to learn CSS/jQuery.
The course is at http://www.codecademy.com/en/skills/make-an-interactive-website/
I agree that you want to get away from non-standard tags. I would also suggest using CSS transitions. Assuming that you want your menu to be accessible once you've scrolled down the page I've used a fixed position container. Hopefully the simplicity of the code will help you understand what is happening.
<div class="menu-container">
<nav>Item 1 | Item 2 | Item 3</nav>
</div>
<div class="content">
<h1>Hello</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. </p>
</div>
CSS
.menu-container {
width: 100%;
height: 30px;
position: fixed; /* Allows you to stick the container in place */
top: 0; /* Stick it to the top of the page */
left: 0; /* Make sure it's all the way to the left as well */
}
nav {
width: 100%;
height: 30px;
background-color: #ccc;
line-height: 30px; /* Easy way to vertically center single line text when you know the height of the container */
border-radius: 0 0 10px 10px;
text-align: center;
position: relative; /* Allows you to adjust placement of element */
top: -31px; /* Move up 30px from its normal position */
transition: all 1s; /* */
}
.menu-container:hover nav {
top: 0; /* When menu-container is hovered move nav to top 0 from -31px */
}
.content {
margin-top: 35px; /* Using this so that your content doesn't start behind the menu */
}
I have a semi-transparent navigation bar that has a fixed position at the top of the window, and content underneath it.
I'd like to make it so that the #content isn't ever visible underneath the navigation bar. Setting the top margin of the content to the same height as the navigation bar works, when the user is at the top of the page. However when the user scrolls down, the content becomes visible underneath the navigation bar.
Basically I'm trying to push/clip the top of the content div, so none of its content is ever visible underneath the navigation bar.
The navigation bar's transparency is particularly important, so simply having an opaque gray background won't work for what I need.
Any suggestions for accomplishing what I'm trying to do?
Code:
http://jsfiddle.net/NAMka/
HTML:
<nav id="top">
<div style="margin: 12px;">foo</div>
</nav>
<div id="content"></div>
CSS:
#top {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 60px;
color: white;
background: rgba(0, 0, 0, 0.7);
}
#content {
margin-top: 60px;
}
JS:
// This is a little cleaner than just manually repeating the p tags.
for (var i = 0; i <= 20; i++) {
$('#content').append('<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut iaculis dolor in sem tempus rutrum. Nullam mattis sodales mi, eu bibendum ante porta quis. Phasellus dui sem, imperdiet at massa in, imperdiet vestibulum leo.</p>');
}
Some mock-ups of what I'm trying to do
This is what the fiddle will look like if you scroll down a little bit. Notice how the content is visible underneath the navigation bar.
Ideally, I'd like the content to be clipped, so it isn't visible underneath the navigation bar.
Update:
Although not ideal, I figured out a somewhat hackish way to achieve what I want involving some JS and the overflow:hidden CSS setting. It seems to work well enough for my purposes.
http://jsfiddle.net/NAMka/4/
HTML:
<nav id="top">
<div style="margin: 12px;">foo</div>
</nav>
<div id="container">
<div id="veil">
<div id="content"></div>
</div>
</div>
CSS:
#top {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 60px;
color: white;
background: rgba(0, 0, 0, 0.7);
}
#container {
background: yellow;
margin-top: 60px;
z-index: -1;
position: relative;
}
#veil {
background: red;
position: absolute;
width: 100%;
left: 0px;
bottom: 0px;
overflow: hidden;
}
#content {
background: blue;
position: absolute;
left: 0px;
bottom: 0px;
}
JS:
for (var i = 0; i <= 6; i++) {
$('#content').append('<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut iaculis dolor in sem tempus rutrum. Nullam mattis sodales mi, eu bibendum ante porta quis. Phasellus dui sem, imperdiet at massa in, imperdiet vestibulum leo.</p>');
}
var height = $('#content').height();
$('#container').height(height);
$('#veil').height(height);
$(window).scroll(function() {
$('#veil').height($('#content').height() - $(window).scrollTop() );
});
You can add a white div that sits beneath the navbar but above the content.
http://jsfiddle.net/naLz7/
HTML
<nav id="top">
<div style="margin: 12px;">foo</div>
</nav>
<div id="bottom"></div>
<div id="content"></div>
CSS
#top {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 60px;
color: white;
background: rgba(0, 0, 0, 0.7);
z-index: 1;
}
#bottom {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 60px;
background: #fff;
z-index: 0;
}
#content {
margin-top: 60px;
}