I have 2 sections:
<section class="notes animate" id="need" style="background:#fff; height:900px; padding-top:70px;">
<!--stuff --->
</section>
<section class="focus" id="need" style="display:none;">
<!--stuff --->
</section>
I want to display the second section when window is lowered to width less than 1043px. And hide the first section by display:none
Update:
How can I remove id attribute of first section, when width is less than 1043?
You should use CSS media queries. You can read more about it here: http://www.w3schools.com/css/css_rwd_mediaqueries.asp
For example:
#media only screen and (max-width: 1043px) {
section.focus {
display: block;
}
}
Firstly you cannot use same ID for more than one div. So change the id of one div.
And to hide the second div and show the first div:
Use CSS:
#media only screen and (max-width: 1043px) {
.focus {
display: block;
}
.notes {
display: none;
}
}
In response to your requirement for removing the ID attribute, try the following JavaScript. It can only do it once however, and if you are interested in performance you should consider investigating debounce/throttle for the resize handler. (http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/)
$(window).on('resize', function() {
if($(window).width() < 1043) {
$('.notes').removeAttr('id');
$(window).off('resize');
}
});
However, the media queries answers are the correct approach to show/hide based on screen width.
Related
I've an html span element as follows:
<span id="display-name" data-name="test123" data-sname="test"></span>
whose content is being set by css media query based on the device width.
#media screen and (min-width: 320px) {
#display-name:after {
content: attr(data-name)
}
}
#media screen and (max-width: 320px) {
#display-name:after {
content: attr(data-sname)
}
}
Later on I want to read the text using javascript as follows:
jQuery(document).ready(function () {
var name = $("#display-name").text();
alert(name);
});
But it appears that the value is not being set by the css. Any help ?
Full example here: http://codepen.io/anon/pen/vgpxwX
Update
The solution posted here : Get Before-Content of CSS with jQuery
is giving a value attr(data-name), but not the value test123 which I need.
Modified codepen: http://codepen.io/anon/pen/vgpxwX
You can use :visible selector to get element that is visible.
<span id="display-name">
<span class="name">test123</span>
<span class="sname">test</span>
</span>
whose content is being set by css media query based on the device width.
#media screen and (min-width: 320px) {
#display-name .name {
display: inline;
}
#display-name .sname {
display: none;
}
}
#media screen and (max-width: 320px) {
#display-name .name {
display: none;
}
#display-name .sname {
display: inline;
}
}
And jQuery
$('#display-name span:visible').text()
When text is set using the content:; property in CSS it's possible to retrieve this using JavaScript by first selecting the pseudo-element with something like:
window.getComputedStyle(document.querySelector('#display-name'), ':before').getPropertyValue('content')
To break this down for you a little more, we're going to find our element:
var el = document.querySelector('#display-name')
Next we need to select its :before pseudo-element
var pseudo = window.getComputedStyle(el, ':before')
Now that we have the pseudo-element selected we can find the value of its content property:
var text = pseudo.getPropertyValue('content')
Here's a demo including sample HTML, CSS, and the JavaScript that will log the same name appearing in our HTML (via the responsive #media queries) in the browser's JavaScript console as well. When the browser goes so narrow CSS changes what's displayed, what is displayed in the console will update as well. In order to ensure that this code runs as the browser is resized note that I added an event listener to run this function on the window resize event!
<div id=display-name name=Jefferson sname=Jeff></div>
<style>
#media (max-width: 500px) {
#display-name:before {
content: attr(sname);
}
}
#media (min-width: 500px) {
#display-name:before {
content: attr(name);
}
}
</style>
<script>
document.addEventListener('DOMContentLoaded',log)
window.addEventListener('resize',log)
function log(){
var el = document.querySelector('#display-name')
var pseudo = window.getComputedStyle(el, ':before')
var text = pseudo.getPropertyValue('content')
console.log(text)
}
</script>
Hope this helps! For more information about getting and setting pseudo-elements from JavaScript, check out this article from David Walsh: https://davidwalsh.name/pseudo-element
The :after pseudo isn't adding the content into the DOM element, so calling .text() will return nothing.
You should read more about the css pseudos.
I've got a left nav div that hides via media query at < 768 and a filter button that displays at < 768. When you click the filter button it uses JQuery to toggle the display of the left nav via show()/hide(). When the window is resized >= 768 I use JQuery to set the display of the left nav back to show.
As I said, my media query handles hiding the left nav when the window width goes below 768, but the problem is it only fires if I have not clicked the filter button. Once I size it under 768 and then click the filter button to turn it on and then click it again to turn it off and then size up over 768 and then back down the left nav is still there. It's like the media query no longer works for the display:none attribute. There are other css properties I change in the media query like width and color and those still work, but it's no longer hiding the div.
I've simplified the code to illustrates the problem.
HTML
Button
<div id="navLeft">NavLeft</div>
CSS
#navLeft {
background-color:orange;
}
#filterButton {
background-color:silver;
display: none;
}
#media only screen and (max-width: 300px) {
#navLeft {
display: none;
}
#filterButton {
display: inline;
}
}
JS
$(window).resize(function()
{
var $theWindowSize = $(this).width();
if($theWindowSize > 300)
{
$('#navLeft').show();
}
});
// Filters
$('#filterButton').bind('click',function(event)
{
event.preventDefault();
if ($('#filterButton').hasClass('filtersActive'))
{
$('#navLeft').hide();
$('#filterButton').removeClass('filtersActive');
}
else
{
$('#navLeft').show();
$('#filterButton').addClass('filtersActive');
}
});
Here's the fiddle. To replicate the behavior follow the steps below.
https://jsfiddle.net/athcy8fL/
1) Resize the width of the Result viewport several times under and above 300px before clicking anything and you'll see everything works as planned. Under 300px the button comes on and the NavLeft div hides. Over 300px and the Button hides and the NavLeft shows
2) Size the Result viewport below 300px and click the Button link. The NavLeft div should appear. Good.
3) Size the Result viewport above 300px and the Button hides. Good.
4) Size the Result viewport below 300px, the NavLeft should hide but it does not. Not Good.
Why doesn't the media query work after using Javascript to alter its display property?
The problem is that when you call .show() in an element that is not already visible, jquery will add an inline style to show the element and override your css, causing the media-query not to work.
I modified your code a little bit to take the inline-style priority into account
http://jsfiddle.net/yjs3fou7/
basically I changed the resize function:
$(window).resize(function()
{
var $theWindowSize = $(this).width();
if($theWindowSize > 300)
{
$('#navLeft').show();
$('#filterButton').removeClass('filtersActive')
} else {
if (!$('#filterButton').hasClass('filtersActive'))
$('#navLeft').hide();
}
});
inline styles have more priority than id or class styles according to css specificity rules so once you start manipulating things from javascript you must remember it may cause your css to stop being applied
The problem is the use of inline styles which has more specificity than the css rules.
$(window).resize(function() {
var $theWindowSize = $(this).width();
if ($theWindowSize > 300) {
$('#navLeft').removeClass('show');
$('#filterButton').removeClass('filtersActive');
}
});
// Filters
$('#filterButton').bind('click', function(event) {
event.preventDefault();
$('#filterButton').toggleClass('filtersActive');
$('#navLeft').toggleClass('show', $('#filterButton').hasClass('filtersActive'));
});
#navLeft {
background-color: orange;
}
#filterButton {
background-color: silver;
display: none;
}
#media only screen and (max-width: 300px) {
#navLeft {
display: none;
}
#filterButton {
display: inline;
}
#navLeft.show {
display: block;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
Button
<div id="navLeft">NavLeft</div>
Demo: Fiddle
I am pretty new at Javascript. I created this effect where text appears under an image icon when the user hovers over it. I would like the effect to only work when the screen is over 768px and for the text to just stay visible at all times when viewed on smaller devices. I've tried using different variants of
if (screen.width < 768px) {}
and
#media all and (min-width: 768px) {} else {}
to control the effect to my liking but without any luck. Help???
Here is my code:
<section id="s1">
<h1><a href="web/services.html">
<img src="images/ICON-TRANSCRIPTION.png" class="hover"></a></h1>
<p class="text">TRANSCRIPTION</p>
</section>
<script>
$('.hover').mouseover(function() {
$('.text').css("visibility","visible");
});
$('.hover').mouseout(function() {
$('.text').css("visibility","hidden");});
</script>
You do not need any JS to do this. The easiest way to accomplish this is to define the media query to be what you desire, set the element to visibility: hidden; and then add a hover rule to change the visibility attribute.
The visibility would be visible by default (on smaller screens), then set to hidden by the media query with the added hover functionality for larger screens.
#media all and (min-width: 768px) {
.hover { visibility: hidden; }
.hover:hover { visibility: visible; }
}
If you must do it via JS(this can be accomplished with CSS media queries), first you should get the width of the window and set it as a variable, then you can set up your conditional statement like so:
function mouseVisibility() {
var w = $(window).width();
if (w > 767) {
$('.hover').mouseover(function() {
$('.text').css("visibility","visible");
});
$('.hover').mouseout(function() {
$('.text').css("visibility","hidden");});
}
}
mouseVisibility();
Additionally, you should fire the function again if the user resizes the browser window:
$(window).resize(function() {
mouseVisibility();
});
I have images of different heights, and I want to place them into a tiled gallery just like the image below is demonstrating:
However, I also want it to be repressive, so my approach to make this work was as follows:
1) Using HTML I created three divs, #grid1, #grid2 and #grid3. And the images are placed inside these 3 grids in anther div that has class .gridElement which contains the images.
<!--Grid System-->
<div id="grid1">
<!--Grid 1-->
<div class="gridElement">
<img alt="image" src="assets/images/image.jpg">
</div>
</div>
<div id="grid2">
<!--Grid 2-->
<div class="gridElement">
<img alt="image" src="assets/images/image.jpg">
</div>
</div>
<div id="grid3">
<!--Grid 3-->
<div class="gridElement">
<img alt="image" src="assets/images/image.jpg">
</div>
</div>
<!--/Grid System-->
2) Here is the CSS using Media Query:
/*Grid System*/
#grid1,#grid2,#grid3 {
width: 33.333%;
float: left;
}
#grid1 {
padding-right: 20px;
}
#grid2 {
padding: 0 10px;
}
#grid3 {
padding-left: 20px;
}
/*Gird Elements*/
.gridElement {
margin-bottom: 30px;
overflow: hidden;
}
#grid1 .gridElement:last-of-type,
#grid2 .gridElement:last-of-type,
#grid3 .gridElement:last-of-type {
margin-bottom: 0;
}
#grid1 img,#grid2 img,#grid3 img {
width: 100%;
}
and
#media screen and (max-width: 1024px) {
/*Grid System*/
#grid1,#grid2,#grid3 {
width: 50%;
}
#grid3 {
display: none;
}
}
and
#media screen and (max-width: 770px) {
/*Grid System*/
#grid1,#grid2,#grid3 {
width: 100%;
}
#grid1,#grid2,#grid3 {
padding: 0;
display: block;
}
#grid1 .gridElement:last-of-type,
#grid2 .gridElement:last-of-type {
margin-bottom: 30px;
}
and
#media screen and (max-width: 500px) {
/*Grid System*/
.gridElement {
margin-bottom: 20px;
}
#grid1 .gridElement:last-of-type,
#grid2 .gridElement:last-of-type {
margin-bottom: 20px;
}
They theory: When the screen size is above 1024px it will show three grids by default. However when the screen size is below 1024px and above 770px using CSS #grid3 is hidden and using JavaScript I am trying to send all of the .girdElements that are inside #grid3 equally to #grid1 and #grid2. When the screen size is below 770px, everying will go back to normal and all the grids will be shown.
The problem? I have managed to get everything working BUT the JavaScript - please can anyone help me to create a function that will send all the .girdElements that are inside #grid3 equally to #grid1 and #grid2 when the screen size is below 1024px and above 770px? "on load, and on resize".
You can use masonry to achieve similar effect. It uses absolute positioning instead of fixed amount of columns. Anyway, it looks the same and adapts to the screen width.
You could try something like this:
var toggle = true;
$('#grid3').children('.gridElement').each(function (index) {
if (toggle) {
$('#grid1').append($(this));
toggle = false;
} else {
$('#grid2').append($(this));
toggle = true;
}
Here is a working example on JSFiddle, sorting elements inside the grids
This solution is better with jQuery, but there are ways to compute actual height of elements.
First, you should mark each item in grid1, grid2, grid3 as belonging to their corresponding grid, e.g. by using a class or data. Then, a kind of "chronology" value that stores the "order" for each item.
If you want all items in grid3 to be appended to grid1 and grid2, you could apply the following algorithm:
Get the items in grid3, sorted by the field. data value, etc. criteria you specified before.
For each item:
a. Compute width of grid1 and compare it to grid of grid2.
b. If grid2 is taller, append the item to grid1. Otherwise append it to grid2.
The column grid3 will be hidden.
A recommended approach is using jQuery to evaluate the .height() of grid1 and grid2, and move the elements.
To go back to a 3-col layout, just take the items with grid3 marker and put them back in grid3, ordered by the chronology value.
(damn, still messing with markdown. please if an editor can help me...)
Try this sample code (not including th fact about sorting criteria - not guaranteed to be flawless - it's just to illustrate the idea):
var grid1 = $("#grid1");
var grid2 = $("#grid2");
var grid3 = $("#grid3");
//compressing - distributing grid3 between grid1 and grid2
function compress()
{
grid3.hide();
$(".item-in-grid3").each(function(i, e){
//never assign "width:" to any grid (1, 2, 3) in css, so it can
//be dynamic and compute height and compare them on each iteration.
if (grid1.height() > grid2.height())
{
$(this).appendTo(grid2);
}
else
{
$(this).appendTo(grid1);
}
});
}
//return back the elements to grid3
function decompress()
{
$(".item-in-grid3").each(function(i, e){
$(this).appendTo(grid3);
});
grid3.show();
}
I have a small problem with jQuery slideDown() animation. When this slideDown() is triggered, it moves all stuff below downwards too.
How do I make all the stuff below the <p> being slid down, remain stationary ?
Note:
I would prefer a solution where the change is done to the <p> element, or to the slideDown call or something. Because in my actual page, there is a lot of stuff below the <p> being slid down, so changing/re-arranging all of them will take much longer for me ~
Demo # JSFiddle: http://jsfiddle.net/ahmadka/A2mmP/24/
HTML Code:
<section class="subscribe">
<button id="submitBtn" type="submit">Subscribe</button>
<p></p>
</section>
<div style="padding-top: 30px;">
<table border="1">
<tr>
<td>This table moves</td>
<td>down when</td>
</tr>
<tr>
<td>slideDown()</td>
<td>is activated !</td>
</tr>
</table>
</div>
JavaScript:
$(function () {
$("#submitBtn").click(function (event) {
$(".subscribe p").html("Thanks for your interest!").slideDown();
});
});
CSS:
.subscribe p {
display: none;
}
You can position that element as absolute:
.subscribe p {
display: none;
position : absolute; // add this line
}
Demo: http://jsfiddle.net/A2mmP/25/
What's happening with your existing code is that the element starts out as display:none; so it doesn't take up any space at all until you slide it in and it is changed to display:block, hence the movement down of the following elements.
With position:absolute it doesn't take up space in that sense, it overlaps: in fact in my updated version of your fiddle you can see a slight overlap into the table underneath - you can obviously tweak margins on the table or whatever to make it fit the way you want.
All you need is to give a fixed height of your .subscribe.
.subscribe {
height: 50px;
}
.subscribe p {
margin: 0px;
display: none;
}
Here is the jsFiddle : http://jsfiddle.net/xL3R8/
Solution
We will put the sliding element in a div element with a fixed width, preventing the document flow from being affected by the slide event.
HTML
<section class="subscribe">
<button id="submitBtn" type="submit">Subscribe</button>
<!-- this is the modified part -->
<div><p></p></div>
</section>
CSS
.subscribe div
{
/* We force the width to stay a maximum of 22px */
height:22px;
max-height:22px;
overflow:hidden;
}
.subscribe div p {
display: none;
/* We reset the top margin so the element is shown correctly */
margin-top:0px;
}
Live Demo
The problem is your CSS, it will render as block and push the other elements down when it slides in. Set it to be absolutely positioned and change the z-index to be in front, or behind.
.subscribe p {
display: none;
position: absolute;
z-index: 100;
}
Fiddle
.subscribe p {
display: none;
margin :0px;
}
IMO a good UI practice would be to, remove the subscribe button, and instead show a message there like :
"Hurray! You have been subscribed"
e.g
http://jsfiddle.net/UvXkY/
$(function () {
$("#submitBtn").click(function (event) {
$("#submitBtn").slideToggle('slow', function(){
$(".subscribe p").html("Thanks for your interest!").slideDown();
});
});
});
The actual problem your facing is display:none which will remove the space for the element p
where as visiblity:hidden and showing will get ride of this problem
Even though it will not give the proper slideDown effects so you can use the position absolute and keep some spaces for the p element will solve your problem.
one of the solution
.subscribe p {
position:absolute;
display:none;
}
.subscribe
{
position:relative;
height:50px;
}
FIDDLE DEMO