Check this jsFiddle.
The orange bar is serving as a progress bar where the value under the circle is how high the progress bar should be.
Any idea why the overflow:hidden; is beeing disregarded and how do one solve this problem? Oblviously nothing should go outside the circle.
Also is there a better solution for this?
Modified your fiddle a little bit. Here is the link
Modifications:
Changed .outerContainer css to display:block from display:table and addedmargin-top:30px to p css
Check if this works for you.
position: absolute and overflow: hidden don't appear to be playing nicely with display: table/table-cell. Removing the table stuff you had in there to vertically center the text fixes the problem. In Firefox, at least.
I think it's the browser thing...
This is the CSS3 version...
.progressBar {
display: block;
width: 100%;
height: 0;
position: absolute;
bottom: 0;
left: 0;
background: #ec6730;
transition: height 1s;
}
.innerContainer:hover > .progressBar {
height: 300px;
}
http://jsfiddle.net/ZyhgT/2/
It no longer flashing 'cause browser handle the job (not js loop animation...). But still it shows the edge on animation finish!!! This could be the browser things... Could be a bug...
This is not related to jQuery or any javascript. In fact, if you delete all your javascript and manipulate the height of your .progressBar using css on li:hover, you will notice the bug anyway.
It appears to be a browser issue as reported on: https://code.google.com/p/chromium/issues/detail?id=157218
As a workaround try adding an imperceptible css transform to the mask element:
.outerContainer {
-webkit-transform: rotate(0.000001deg);
}
You just need to change your .outerContainer class and it works just fine!
.outerContainer {
position: relative;
display: block;
height: 96px;
width: 96px;
overflow: hidden;
background: #fff;
border: 2px solid #fff;
-webkit-border-radius: 50px;
border-radius: 50px;
}
Put the level class inside the outerContainer div and style the span inside the level class to be relatively positioned. In the JavaScript, to calculate the level, divide by 10 instead of 100 for the perfect circular hover effect.
Here is a fiddle.
HTML
<div class="outerContainer">
<div class="innerContainer">
<p>Circle 3</p>
<span class="progressBar"></span>
</div>
<div class="level"><span>75</span>
</div>
</div>
CSS
body {
background: blue;
}
#circles {
text-align: center;
margin: 100px 0;
}
li {
display: inline-block;
margin: 0 10px;
position: relative;
}
.outerContainer {
position: relative;
display: block;
height: 96px;
width: 96px;
overflow: hidden;
background: #fff;
border: 2px solid #fff;
-webkit-border-radius: 50px;
border-radius: 50px;
}
.innerContainer {
display: table-cell;
vertical-align: middle;
width: 100%;
margin: 0 auto;
text-align: center;
}
p {
color: #000;
width: 96px;
position: relative;
z-index: 2;
}
.progressBar {
display: block;
width: 100%;
height: 0;
position: absolute;
bottom: 0;
left: 0;
background: #ec6730;
}
.level span{
position:relative;
}
JS
$(function() {
$("#circles li").hover(function(){
var thisElement = $(this);
var level = $(this).find(".level").text();
var elementHeight = $(this).find(".outerContainer").height();
level = (level/10)*elementHeight;
$(thisElement).find(".progressBar").stop().animate({
height: level
}, 300);
}, function() {
var thisElement = $(this);
$(".progressBar").stop().animate({
height: 0
}, 300);
});
});
display: table doesn't work that good with CSS positioning;
you should avoid using that, and find some other way to vertically center your labels.
If your circles have a known height, like your code seems to indicate (height:96px ecc), then just use a fixed top position for an absolutely positioned <p> element:
http://jsfiddle.net/ZyhgT/5/
Note that you don't even need jQuery for this, it is all achievable with just CSS3 (unless you are targeting old browsers)
Related
Background
I have an HTML div which contains a ‘tooltip’-like feature (i.e., a text box pops up when a certain element is clicked or hovered over); this tooltip has decorative pseudo-elements to make it look like a ‘speech bubble,’ added in css as :before and :after .
I have a JS script, which is intended to show and hide the tooltip and decoration, in response to click events (i.e., toggle them between ‘show’ and ‘hide’ states).
Problem
I can’t get the decorative pseudo-elements to hide when the tooltip is hidden; as pseudo-elements, they are not part of the DOM and so I can’t use normal selectors to manipulate them.
When the tooltip is hidden on click, the decorative pseudo-elements persist, which is not a usable result.
I can’t do away with the decorative elements, they are part of the work specification.
Approach tried so far
Based on this question, my thought was to add an empty span with its own class, to which I’d prepend and append these pseudo-elements. Then, add or remove the class on click based on whether it exists already, or not.
I have also tried setting the class to which the pseudo-elements are pre/appended to display:none on click, but this also seems not to work
However, I cannot convince the pseudo-elements to hide on click.
I’ve included a screenshot of what these remnant pseudo-elements look like in the live environment.
Note: I tried to work up a running simulation for the purpose of this question, but I wasn’t able to and the original css file is massive; the code included below is for reference only.
All guidance is much appreciated!
const barContainer = document.querySelector(".bar-container");
const decorationElement = document.querySelector("#decoration");
document.addEventListener('click', function(event) {
console.log('click event listener triggered');
if (event.target.closest('.link') || event.target.classList.contains('link')) {
if (barContainer.classList.contains('open')) {
barContainer.classList.remove('open')
decorationElement.classList.remove('decoration')
document.querySelector('.tooltip-container').setAttribute('style', 'display:none');
} else {
barContainer.classList.add('open')
decorationElement.classList.add('decoration')
document.querySelector('.tooltip-container').setAttribute('style', 'display:block');
}
} else {
barContainer.classList.remove('open')
decorationElement.classList.remove('decoration')
document.querySelector('.tooltip-container').setAttribute('style', 'display:none');
}
});
.foo-container {
height: auto;
position: relative;
}
.bar-container {
height: auto;
position: relative;
text-align: center;
}
.bar-container:hover .tooltip-container,
.tooltip-container:hover,
.bar-container.open .tooltip-container {
position: absolute;
display: block;
text-align: left;
background-color: #ffffff;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
bottom: 50px;
right: 5%;
border-radius: 4%;
font-weight: 300;
max-width: 90%;
font-size: 14px;
padding: 20px 0;
}
/*the below two rule sets create the rotated 'decoration' */
.bar-container:hover .tooltip-container:before,
.tooltip-container:hover:before,
.bar-container.open .tooltip-container:before,
.foo-container .bar-container:hover .decoration:before {
content: "";
width: 65px;
height: 35px;
position: absolute;
overflow: hidden;
transform: rotate(-180deg);
z-index: 10;
bottom: 0;
left: 170px;
background-color: white;
}
.foo-container .bar-container.open .decoration:before,
.foo-container .bar-container:hover .decoration:before {
content: "";
position: absolute;
width: 30px;
height: 30px;
background: #fff;
transform: rotate(45deg);
left: 30px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
z-index: 2;
top: -42px;
}
/* end 'deocration' */
<div class="foo-container">
<div class="bar-container">
<p>text <span class='link'>the-link<span id='decoration' class='decoration'></span></span>
</p>
<div class='tooltip-container'>
<p>lorem </p>
</div>
</div>
</div>
Screenshot of the undesirable 'persistent pseudo-elements' behavior -->
I have pictures in a horizontal scroll and I want to be able to hover over each image, and when I do, I want the picture to be slightly "grayed out" with text over it.
I can't for the life of me figure out how to do it.
I made this fiddle to show what my scroll bar looks like.
https://jsfiddle.net/burgoyne/u1zdn80p/1/
#scroll {
height: 25%;
overflow-x: scroll;
white-space: nowrap;
width: 50%;
}
#scroll img {
height: 100%;
vertical-align: top; /* this prevents vertical whitespace */
}
Can someone point me in the right direction here? I have been trying different things with CSS to gray it out and add text, with no luck.
Thanks!
You have to specify what you want in a CSS img:hover rule, like this:
html, body {
height: 100%;
margin: 0;
padding: 0;
width: 100%;
}
#scroll {
height: 25%;
overflow-x: scroll;
white-space: nowrap;
width: 50%;
}
#scroll img {
height: 100%;
vertical-align: top; /* this prevents vertical whitespace */
}
#scroll img:hover {
opacity: .5;
}
<div id="scroll">
<a href="http://www.google.ca"><img src="http://www.fotoviva.co.uk/image/cache/data/prods/doug-blue-lake-500x500.jpg" /><!--
--><a href="http://www.google.ca"><img src="http://wannasmile.com/wp-content/uploads/2009/09/c76c_Gordon-McBryde-Field-Sunset-500x500.jpg" /><!--
--><a href="http://www.google.ca"><img src="http://creativefan.com/important/cf/2012/10/patio-garden-ideas/nice-patio-gardeen.jpg" /><!--
--><a href="http://www.google.ca"><img src="http://globotours.net/wp-content/uploads/2015/05/Desert-Safari-Dubai-500x500.jpg" />
</div>
About the gray color over the image, you can just add opacity to the image on hover ("opacity: 0.5") and, if you want, some transition between the event and the "grayness" with "transition: 0.5s" or so.
About the problem with the text overlay, I think you should visit this answer: Text on image mouseover?
You can place text inside with class named
<span class="text-content"><span>Some text here</span></span>
and then u can use css to place text on the image, something like ...
span.text-content
{
background: rgba(0,0,0,0.5);
color: white;
cursor: pointer;
display: table;
height: 150px;
left: 0;
position: absolute;
top: 0;
width: 150px;
}
span.text-content span
{
display: table-cell;
text-align: center;
vertical-align: middle;
}
I hope this helps.
I want to make a vertically draggable division of two areas like the following.
I just want to modify a online example of draggable divs to be what I want. Finally, I got this. Can someone give me some hints to modify it?
JSFiddle Link : https://jsfiddle.net/casperhongkong/omekvtka/14/
HTML
<div class="container">
<div class="area1">
Area 1
</div>
<div class="drag">
</div>
<div class="area2">
Area 2
</div>
</div>
CSS
.container {
position: fixed;
top: 51px;
right: 0px;
bottom: 0px;
left: 0px;
background-color: #272822;
border: 1px solid #222;
// margin: 0 auto;
//display: inline-block;
}
.area1 {
position: absolute;
height: 100%;
width: 30%;
background-color: #ddd;
display: inline-block;
}
.drag {
position: fixed;
width: 5px;
height: 100%;
background-color: #444;
display: inline-block;
}
.area2 {
position: absolute;
right: 0;
height: 100%;
width: 30%;
background-color: #ddd;
display: inline-block;
}
JavaScript
$(document).ready(function() {
$('.drag').on('mousedown', function(e) {
var $area1 = $('.area1'),
$area2 = $('.area2'),
startWidth_a1 = $area1.width(),
startWidth_a2 = $area2.width(),
pX = e.pageX;
$(document).on('mouseup', function(e) {
$(document).off('mouseup').off('mousemove');
});
$(document).on('mousemove', function(me) {
var mx = (me.pageX - pX);
$area1.css({
width: startWidth_a1 - mx;
});
$area2.css({
//left: mx / 2,
width: startWidth_a2 - mx,
//top: my
});
});
});
});
For javascript, I would recommend checking out a library, as this is slitghtly more complicated than just a few lines. #fauxserious gave Split.js as a fantastic example.
This is possible in pure HTML/CSS, though slightly limited, as discussed here.
HTML:
<div class="split-view">
<div class="resize-x panel" style="width: 216px;">
Panel A
</div>
<div class="panel">
Panel B
</div>
</div>
CSS:
/* Panels: */
.panel{
padding: 1em;
border-width: 6px;
border-style: solid;
height: 4em;
}
/* Resizing */
.resize-x {
resize: horizontal;
overflow: auto;
}
/* Split View */
.split-view {
margin: 1em 0;
width: 100%;
clear: both;
display: table;
}
.split-view .panel {
display: table-cell;
}
Based on #afischer's table-cell solution, here is an alternative one.
I have had to put accordions within the left side panel.
The sticky headers of the accordions require overflow to be visible,
while resize requires overflow to be anything but visible:
https://caniuse.com/#feat=css-sticky.
In the same time, I didn't need anything to place into the right side panel.
Thus, an overcome was employing resize on the right panel, and rotating by 180 deg to get the dragable side to the middle, as well as this way the dragable corner relocated to the top (visible without scrolling).
Plus some highlight has been added to the dragable corner.
/* Panels: */
.panel{
padding: 1em;
border-width: 6px;
border-style: solid;
height: 4em;
}
/* Resizing */
.resize-x {
resize: horizontal;
overflow: auto;
transform: rotate(180deg);
border-right: solid gray 1px;
}
/* Split View */
.split-view {
margin: 1em 0;
width: 100%;
clear: both;
display: table;
}
.split-view .panel {
display: table-cell;
}
.resize-x::-webkit-resizer {
border-width: 8px;
border-style: solid;
border-color: transparent orangered orangered transparent;
}
<div class="split-view">
<div
class="panel"
style="width: 216px;">
Panel A
</div>
<div class="panel resize-x">
Panel B
</div>
</div>
Unfortunately there are two disappointing thing with the above:
Firefox cannot handle the combination of table-cell and resize
Only a corner of the grabber is responsive, which can even be scrolled out easily
Here is an other solution which also takes the above two problems into account
without resize CSS property
and with full height responsive grabber
It's a combination of a flexbox and an input:range slider.
The trick is that the pointer-event CSS property can be different
on the slider's background
and on its grabber.
The slider covers the entire view. The background of the slider is transparent for the events too (pointer-events: none), while the dragbar itself catches the events (pointer-events: auto).
It requires minor Javascript and because I've implemented the production version in Nuxt.js, I use Vue.js here, instead of vanilla JS.
new Vue({
el: '#vue',
data: {
windowWidth: null,
splitWidth: null,
},
mounted() {
this.windowWidth = window.innerWidth;
// For arbitrary initial position:
this.splitWidth = this.windowWidth * 2/3;
},
computed: {
flexRatio() {
return this.splitWidth / this.windowWidth;
}
}
})
body {
margin:0;
}
main {
display: flex;
width: 100%;
height: 100vh;
}
article {
display: flex;
}
section {
width: 100%;
height: 100%;
text-align: justify;
padding: 20px;
}
.section-left {
background-color: darkseagreen;
}
.section-right {
background-color: orangered;
}
#split-grabber {
pointer-events: none;
position: fixed;
top: 0; right: 0; bottom: 0; left: 0;
-webkit-appearance: none;
/* Safari allows dragging behind scroll bar.
We fix it by shrinking its width on the right side via both
its range value :max="windowWidth - 12"
and its width (CSS) width: calc(100% - 12px)
...synchronously */
width: calc(100% - 12px);
height: 100vh;
background: transparent;
outline: none;
margin: 0;
}
#split-grabber::-webkit-slider-thumb {
z-index: 1;
pointer-events: auto;
-webkit-appearance: none;
appearance: none;
width: 5px;
height: 100vh;
background: lightgray;
box-shadow: 1px 2px 2px 0px gray;
cursor: col-resize;
}
#split-grabber::-moz-range-thumb {
z-index: 1;
pointer-events: auto;
-webkit-appearance: none;
appearance: none;
width: 5px;
height: 100vh;
background: lightgray;
box-shadow: 1px 2px 2px 0px gray;
cursor: col-resize;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<main id="vue">
<!-- Safari allows dragging behind scroll bar
We fix it by shrinking its width on the right side via both
its range value :max="windowWidth - 12"
and its width (CSS) width: calc(100% - 12px)
...synchronously -->
<input
id="split-grabber"
type="range"
v-model="splitWidth"
:max="windowWidth - 12"
>
<article
class="article"
:style="{'flex': flexRatio}"
>
<section
class="section section-left">
splitWidth:{{ splitWidth }}px<br>
“There was a rich man who always dressed in the finest clothes and lived in luxury every day.
And a very poor man named Lazarus, whose body was covered with sores, was laid at the rich man’s gate.
He wanted to eat only the small pieces of food that fell from the rich man’s table. And the dogs would come and lick his sores.
Later, Lazarus died, and the angels carried him to the arms of Abraham. The rich man died, too, and was buried.
In the place of the dead, he was in much pain. The rich man saw Abraham far away with Lazarus at his side.
He called, ‘Father Abraham, have mercy on me! Send Lazarus to dip his finger in water and cool my tongue, because I am suffering in this fire!’
</section>
</article>
<article
class="article"
:style="{'flex': 1-flexRatio}"
>
<section class="section section-right">
But Abraham said, ‘Child, remember when you were alive you had the good things in life, but bad things happened to Lazarus. Now he is comforted here, and you are suffering.
Besides, there is a big pit between you and us, so no one can cross over to you, and no one can leave there and come here.’
The rich man said, ‘Father, then please send Lazarus to my father’s house.
I have five brothers, and Lazarus could warn them so that they will not come to this place of pain.’
But Abraham said, ‘They have the law of Moses and the writings of the prophets; let them learn from them.’
The rich man said, ‘No, father Abraham! If someone goes to them from the dead, they would believe and change their hearts and lives.’
But Abraham said to him, ‘If they will not listen to Moses and the prophets, they will not listen to someone who comes back from the dead.’”
</section>
</article>
</main>
I was wondering if anyone can give me some insight on javascript/jquery for div expansion. In the JSFiddle you will find:
Four black divs:
.first_box {
width: 142px;
height: 142px;
margin-left: 0px;
margin-top: 0px;
position: absolute;
display: table;
background-color: black;
}
A unique hover color for each div:
.first_box:hover {
width: 142px;
height: 142px;
margin-left: 0px;
margin-top: 0px;
position: absolute;
display: table;
background-color: green;
}
So my question is:
What can I use so that when a div is clicked, it expands to the size of the four divs (289 X 289)?
The expanded div will then be filled with unique content.
Thank you!
JSFiddle: http://jsfiddle.net/SXfeG/1/
If you use absolute positionning, you can add some CSS like that :
.div-clicked {
width: 289px !important ;
height: 289px !important ;
margin-top: 0 !important ;
margin-left: 0 !important ;
z-index: 400 ;
}
div {
transition: all 1s ; // To add transition effect
}
And then, with jQuery, you can toggle 'clicked' class simply by using :
$('div').on('click', function (e) { $(this).toggleClass('clicked') ; })
JSFiddle : http://jsfiddle.net/85QFN/
This question already has answers here:
Selecting and manipulating CSS pseudo-elements such as ::before and ::after using javascript (or jQuery)
(26 answers)
Closed 5 years ago.
Markup:
<h1 class="title">Hello World</h1>
CSS:
.title {
border-bottom: 3px solid #aaa;
position: relative;
}
.title:after {
content: "";
width: 100px;
border-bottom: 3px solid red;
display: block;
position: absolute;
}
Demo: http://codepen.io/anon/pen/HDBqe
I wanted to change the .title:after's width based on the text's width, how do I change :after's width using javascript?
$.fn.textWidth = function(){
var html_org = $(this).html();
var html_calc = '<span>' + html_org + '</span>';
$(this).html(html_calc);
var width = $(this).find('span:first').width();
$(this).html(html_org);
return width;
};
$('.title').each(function(){
// Change :after's width based on the text's width
// .css('width', $(this).textWidth());
});
I've found a trick which works in this case. I've updated your demo:
http://codepen.io/anon/pen/bHLtk
.title {
border-bottom: 3px solid #aaa;
position: relative;
min-width: 100%;
}
.title:after {
content: "";
width: inherit;
border-bottom: 3px solid red;
display: block;
position: absolute;
}
Notice, that .title:after has width set to inherit but his parent (.title) has overridden width with min-width. Now I can freely to set width by JavaScript to title and it take effect only on his nested pseudoelement:
$('.title').each(function(){
$(this).css('width', $(this).textWidth());
});
A pseudo-element is not part of the DOM. Therefore, you cannot change its CSS properties directly through JS.
In order to get your desired effect the way you want it, my best guess would be YUI.StyleSheet and manipulate the stylesheet itself, although I have to admit I haven't tested it myself in recent years.
Including such a utility and doing all of this calculation seems like a lot of work for width matching.
If you are willing to compromise a little bit on the semantic HTML, there is a working technique:
Your element takes the entire width of the screen. Wrapping the text with a span and adding the pseudo-element to that, as an inline-block should allow you to get the border under the text only
HTML:
<h1 class="title"><span>Hello World</span></h1>
CSS:
.title {
border-bottom: 3px solid #aaa;
position: relative;
}
.title span{
display:inline-block;
position:relative;
}
.title span:after {
content: "";
width: 100%;
border-bottom: 3px solid red;
display: block;
position: absolute;
}
Here is my version of the codePen.
For future reference:
There is a W3C Candidate Recommendation that suggests the capability of using attributes for CSS properties other than content.
This way, if and when the recommendation is approved and implemented, it might be possible to have the pseudo-element reflect the parent's attributes, as such:
this.setAttribute("length", $(this).textWidth());
And the relevant CSS:
.title:after {
...
width: attr(length px);
...
}
How's this for a different approach.... http://jsfiddle.net/mayYt/
Added CSS
.title span {
border-bottom: 3px solid red;
}
JQuery
$('.title').wrapInner('<span />');
With just a simple trick any pseudo-element can be changed (or at least replaced with something else):
$('.something').click(function(){
$(this).toggleClass('to_show');
});
.something
{
background: red;
height: 40px;
width: 120px;
position: relative;
}
.something.to_show:after
{
content: "X";
color: white;
background: green;
width: 20px;
height: 20px;
position: absolute;
right: 0px;
top: 0px;
display: block;
text-align: center;
}
.something:after
{
content: "O";
color: white;
background: blue;
width: 30px;
height: 25px;
position: absolute;
right: 0px;
top: 0px;
display: block;
text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<div class="something">
click here!
</div>
</body>
</html>