I've just revamped my tooltip code due to issues with the position altering depending on the size of it's parent (mostly due to using offsetX/Y instead of pageX/Y, but page was being weird, too). So I decided to just have one tooltip for each of my site's pages, parented to the main div, and just feed it different text depending on what the mouse is hovering over (I'll be dealing with the visibility part later).
And it's worked quite well so far, but the only issue is that, the smaller I make my window, the farther the tooltip is from my mouse, until it's not even in view anymore.
Here's the JavaScript coding I've done for it.
var body = document.getElementsByClassName("test");
var tooltip = document.getElementById("tooltip");
body[0].addEventListener("mousemove", tooltipMove)
function tooltipMove(event) {
var x = event.pageX;
var y = event.pageY;
tooltip.style.top = (y + -900) + "px";
tooltip.style.left = (x + -875) + "px";
}
The CSS coding for the tooltip:
.tooltip {
visibility: hidden;
width: 170px;
background-color: white;
background-image: url("images/tooltipbackground.png");
color: black;
text-align: center;
border-style: groove;
border-color: #f4bb4c #ffd966 #ffd966 #f4bb4c;
border-radius: 2px;
padding: 5px 5px;
position: absolute;
z-index: 1;
}
.notfound:hover .tooltip {
visibility: visible;
}
And the HTML:
<div class="test" style="top: 70px; position: relative; height: 100%; width: 100%;">
<h1>TEST</h1>
<img src="images/pagenotfound.png">
</div>
<div style="width: 1px; height: 1px; position: relative;">
<span class="tooltip" id="tooltip">testing</span>
</div>
I should mention the body's (which has the "notfound" class) height is 900px, and it's width 600px, in case that's one of the problems.
The 1 pixel div is just what I'm using to "host" the tooltip, not sure if it's causing any problems as well. I inspected the page in order to see it, and it never seemed to slide around with the window size.
Any sort of help would be greatly appreciated. I've tried to switch it from pageX/Y to clientX/Y, but it's the same issue. And using offset causes it's position to shift depending on what I'm hovering over, which is the reason I'm revamping the code in the first place.
I've also tried to change the tooltip's position from absolute to, well, anything else (after resizing it's parent so it doesn't get squashed), but that hasn't helped.
Another thing I should mention is that, for some reason, the shifting doesn't seem to happen in the Y axis, it's only when I squish the window horizontally that the tooltip shifts, at least from what I've noticed.
I had thought changing the tooltip's position to fixed had made it disappear, but I just couldn't see it due to the massive repositioning I had done to it. Once I deleted that it was visible and fine, and better yet, it stays in it's proper position no matter the screen size!
Also note: I had to change pageX/Y to clientX/Y, as using page made the tooltip shift vertically when squished.
<div style="height: 1px; width: 1px; position: relative;">
<span class="tooltip" id="tooltip" style="position: fixed;">Placeholder</span>
</div>
for (i = 0; i < tip.length; i++) {
tip[i].addEventListener("mousemove", tooltipMove)
tip[i].addEventListener("mouseleave", defaultVis)
}
function tooltipMove(event) {
var x = event.clientX;
var y = event.clientY;
tooltip.style.visibility = "visible";
tooltip.style.top = (y + -50) + "px";
tooltip.style.left = (x + -200) + "px";
}
function defaultVis() {
tooltip.style.visibility = "hidden";
}
I'm very newbie to webdev, but I need to draft a landingpage with some trick effects.
I need to put a "stencil image" (png with transp) over a moving (mouse hover) background.
Basically, I managed to do that, but I having a big issue: If I resize browser, the background shows behind first plane image, (because I can't rezise background to browser size).
So, the main codes are:
html code:
<div id="bkg-image" class="blur"></div>
<div>
<img src="./imgs/stencil.png" class="firstPlane" />
</div>
CSS code:
#bkg-image {
background: url('./imgs/background.jpg') no-repeat center center fixed;
position: absolute;
-webkit-background-size: cover;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
width: 75%;
height: 75%;
z-index: 0;
-webkit-filter: brightness(1.7);
}
.firstPlane {
display: block;
position: absolute;
top: 0px;
left: 0px;
max-width: 100%;
height: auto;
width: auto;
z-index: 2;
}
JS code:
$(document).ready(function() {
var movementStrength = 75;
var height = movementStrength / $(window).height();
var width = movementStrength / $(window).width();
$(".firstPlane").mousemove(function(e) {
var pageX = e.pageX - ($(window).width() / 2);
var pageY = e.pageY - ($(window).height() / 2);
var newvalueX = width * pageX * -1;
var newvalueY = height * pageY * -1;
$('#bkg-image').css("background-position", newvalueX + "px " + newvalueY + "px");
});
});
Any idea how to crop the excess background or how to rescale it to fit behind firstplane image?
note: blur class is just for an animated blur effect, not relevant to this.
I took the java script from a net tutorial.
My first aproach was using webkit mask-image, but seens it don't works, now I'm trying this method.
Thanks a lot for any help
You are doing it upside down. This is how it should be.
$(document).ready(function() {
$("#bkg-image").mousemove(function(e) {
$('.firstPlane').css({left: e.pageX + "px", top: e.pageY + "px"});
});
});
I need invert the selection: I need read the mouse position on first plane and apply movement to the bkg image. (your script only works if I switch #bkg-image and .firstPlane). My issue isn't read the movement, but crop bkg-image to not show it bellow 1st plane when I have a small and tall browser window.
The solution would be a mask/clip image, but its not working for svg graphics or PNG for me, so I give up and tried with a big black PNG with transp on it to show background.
Something like this: (https://codepen.io/caraujo/pen/rVOZKJ) but with a logo (vector or png), but mask/image clip is not working for me :/
I've made a script that re-sizes my website with some ratio: 'rat'. I do a scale but that scale creates white margins so I transform the entire html page and I sent it to origin in the coordinates 0 , 0.
document.documentElement.style.transform = "scale(" + rat + ")";
document.documentElement.style.width = 100 / rat + "%";
document.documentElement.style.transformOrigin = '0 0';
The problem I have is that some background images with the following property do not transform:
background-attachment: fixed;
Everytime I transform my html page the background images with background-attachment: fixed; don't transform.
You can check what I'm talking about in my portfolio here:
http://testedesignfranjas.tumblr.com/
Open the site in chrome and in FIREFOX and see the differences.
The issue is in Firefox.
*sorry for my bad english
I have a partial answer. Firefox doesn't always treat nested, fixed elements correctly when using a transform. Instead of using background-attachment, make the div with the image position:fixed. The second div is relative or static, so it will overlay the first div.
<body onload="scaleAll(0.8)">
<div id="img1">I have a background image, am scaled and am fixed.</div>
<div id="outer">
I have content and am scaled.
</div>
</body>
I have moved the image outside the div and set img1 to position:fixed. Do the scaling individually, once for img1 and once for the outer div that has the content.
<script>
function scale(rat, container) {
var element = document.getElementById(container);
element.style.transform = 'scale(' + rat + ')';
element.style.transformOrigin = '0 0';
}
function scaleAll(rat) {
scale(rat, "outer");
scale(rat, "img1");
}
</script>
The style uses position:fixed for the img1 and relative for the outer.
<style>
div#outer {
position: relative;
height: 900px;
width: 900px;
}
#img1 {
position: fixed;
background: url("image.png") no-repeat;
width: 796px;
height: 397px;
}
</style>
JSFiddle Example
Use jQuery to remove the "fixed" attribute when you scale document
$("img").each(function() {
$(this).css("background-attachment","");
});
I'm desperately searching for solution for my client. I have graphic - something like that:
And I want to be able to take the line with circle in the center and drag it to right or left. And it will be hiding and unhiding my two full images. It's basically two images on the same place, just with another z-index I think.
I think it's possible to do it with JavaScript, but I don't know of any functions or methods for this option.
Here is my solution:
The HTML is pretty simple, just two divs for the images and one for the drag:
<div class="img" id="img1"></div>
<div class="img" id="img2"></div>
<div id="drag"></div>
For the CSS, the important part is to absolute position all the divs and give a background image.
As for the Javascript, with a little help from jQuery, we listen for the mouse events, make some calculations and adjust the CSS of the second image:
$('#drag').on('mousedown', function(e){
var $self = $(this),
dragPos = $self.position().left + $self.width()/2,
imgWidth = $('#img1').width();
$(document).on('mouseup', function(e){
$(document).off('mouseup').off('mousemove');
});
$(document).on('mousemove', function(me){
var mx = me.pageX - e.pageX + dragPos
$self.css({ left: mx });
$('#img2').css({
width: imgWidth - mx,
left: mx,
backgroundPosition: -mx + 'px 0px',
});
});
});
From there, I believe it's pretty easy to customize it and give it a unique look.
Hope this helps!
JsFiddle Demo
Something like this alphamask plugin may do the trick, though I'm not sure how simple it would be for you to implement in the manner of your slider example.
Actually quite simple. The first step is to make it work manually. I'd set it up as follows:
<div class="wrap" id="wrap1">
<div class="img-wrap img1"></div>
<div class="img-wrap img2"></div>
<div>
With CSS as follows:
.wrap {
position: relative;
width: 300px;
height: 300px;
}
.img-wrap {
width: 100%;
height: 100%;
position: absolute;
top: 0px;
left: 0px;
}
.img1 {
z-index: 1;
background: url(bg1.png) no-repeat 0px 0px;
}
.img2 {
z-index: 2;
background: url(bg1.png) no-repeat 0px 0px;
}
Now some JavaScript (with jQuery) to set a position (you can call this when you move a slider over the top later):
function setPosition(percentage){
// get the width of the container
var w = $('#wrap1').width();
// work out the width of left panel
var w1 = Math.floor(w * percentage);
// and the right panel
var w2 = w - w1;
// set the width of the right panel
// move it right by the width of the left panel
// and move the background back by the width of the left panel
$('#wrap1 .img2').css({
width: w2,
left: w1,
backgroundPosition: -w1 + 'px 0px',
});
}
You now just have to decide how to do the dragging. You could even just do it on mouseOver. Easy!
I'm looking to make a page that has a background gradient that changes color every few seconds and blends between transitions. Now I want to apply this effect on the to the upper elements that are blocked by a element that has a solid background.
To give you a better example what I mean I have attached a simple mockup and hopefully your understand what I'm attempting to do, I'm open to suggestions.
(source: bybe.net)
The problem is obviously the block that contains the black background which any PNG transparent used would see black not the gradient.
I'll include sample code so far:
<body><!-- A Jquery script will be used to add CSS background, Easy stuff -->
<div class="blackbox">
<div class="logo"><img src="#" alt=""></div>
<hr class="h-line">
<div class="v-line"> </div>
</div>
So what I'm after is either:
A known jQuery method to obtain a background image but it needs to be able to refer of the position of the gradient so its inline with the background.
A better solution to getting this to work, please bare in mind that the page needs to be responsive so I could use other methods but since its responsive I can't think of any.
Since you ask for alternatives to jQuery solutions
You could play a little with margins and box-shadow and keyframe animations.
Something in this direction for the shape (depends on what you want to do with which part - add content ... and in what way you want it to be responsive):
html:
<div class="wrapper">
<div class="header"><img src="http://i.imgur.com/CUbOIxr.png" alt="Company name" /></div>
<div class="content"></div>
</div>
CSS:
body {
background:orange;
width:100%;
height:100%;
}
.wrapper {
width:40%;
height:90%;
border:30px solid #000;
border-right-width:100px;
border-bottom-width:100px;
}
.header {
width:100%;
border-bottom:10px solid transparent;
-webkit-box-shadow: 0 30px 0 #000;
-moz-box-shadow: 0 30px 0 #000;
box-shadow: 0 30px 0 #000;
}
.header img {
width:100%;
}
.content {
width:95%;
height:400px;
background-color:#000;
margin-top:30px;
}
DEMO
This way no javascript is needed. And for the background you can use a linear gradient and do all animations with css transitions or keyframe animations. You also need to play with the lengths and adjust the borders and box-shadows to your needs, maybe add some #media queries for the responsiveness.
Hope this helps you a little in the right direction =)
Update:
I hoped the gradients changing was the smaller problem ;-) Silly me, sorry.
I will elaborate my CSS-only suggestion for the animation, but you can choose a javascript slider for the background animation, if you don't like CSS3 solutions - although this is the hot stuff now ;-)
Ok. So, I would add some more fixed positioned elements with gradient backgrounds (layer1 and layer2).
To have something in this direction in the html now:
<div class="layer layer1"></div>
<div class="layer layer2"></div>
<div class="wrapper">
<div class="header">
<img src="http://newtpond.com/test/company-name.png" alt="Company name" />
</div>
<div class="content"></div>
</div>
and add a keyframe animation on them in CSS (here it is just with the -webkit vendor prefix [probably cause I am a lazy bum], but I hope you can get the idea, and could add the others):
body {
width:100%;
height:100%;
margin:0;
padding:0;
}
/* for the animation */
.layer {
position:fixed;
width:100%;
height:100%;
}
#-webkit-keyframes GoLayer1 {
0% {
opacity:1;
}
50% {
opacity:0;
}
100% {
opacity:1;
}
}
#-webkit-keyframes GoLayer2 {
0% {
opacity:0;
}
50% {
opacity:1;
}
100% {
opacity:0;
}
}
.layer1 {
background: -webkit-linear-gradient(bottom, rgb(43, 70, 94) 29%, rgb(194, 41, 41) 65%, rgb(155, 171, 38) 83%);
-webkit-animation: GoLayer1 5s infinite;
}
.layer2 {
background: -webkit-linear-gradient(bottom, rgb(225, 202, 230) 29%, rgb(39, 163, 194) 65%, rgb(36, 124, 171) 83%);
-webkit-animation: GoLayer2 5s infinite;
}
/* the wrapper shape */
.wrapper {
z-index:999;
opacity:1;
position:relative;
width:40%;
height:90%;
border:30px solid #000;
border-right-width:100px;
border-bottom-width:100px;
}
.header {
width:100%;
border-bottom:10px solid transparent;
-webkit-box-shadow: 0 30px 0 #000;
-moz-box-shadow: 0 30px 0 #000;
box-shadow: 0 30px 0 #000;
}
.header img {
width:100%;
}
.content {
width:95%;
height:400px;
background-color:#000;
margin-top:28px;
}
DEMO (tested in Chrome 26 - looked cool =)
This is now where I can point you according this CSS-only approach. There is still stuff to modify and consider browser compatibility. But it is certainly an alternative ... and a step in the direction where html5 and css3 is going (if you want to be hot and cool ;-), hehe, sorry, too much silliness.
Good luck!
Update 2:
So, I overcame my laziness a tiny bit and added some more vendor prefixes to the top example (and of course you can use any image as background):
DEMO
And here I add another example, that is using a png image for the gradient, and is sliding up and down in the background (as another alternative):
DEMO
There are many ways to do this, CSS3 and images are already suggested, so I'll suggest using a canvas.
The HTML canvas element has everything you need built in. It allows for gradient background fills, and with globalCompositeOperation, masking of shapes and text is possible, creating cut-outs in the background to make real changeable HTML elements truly transparent against a colored background. It also scales well, and can easily be made responsive.
The canvas element is supported in all major browsers except Internet Explorer 8 and below, which means browser support is better than many of the CSS3 methods previously mentioned, like keyframes and background-size.
Using a fallback, like say images that fade in and out if canvas is'nt available, should'nt be very hard to figure out, and in all other browsers except Internet Explorer below version 9, no images would be needed to create the gradient backgrounds and text masks in a canvas, which should make the loading of the page significantly faster.
To detect wether or not canvas is supported, you can use this convenient function :
function isCanvasSupported(){
var elem = document.createElement('canvas');
return !!(elem.getContext && elem.getContext('2d'));
}
used like so :
if ( isCanvasSupported() ) {
// do canvas stuff
}else{
// fall back to images
}
So, lets get to it! To create a "last resort" fallback and some elements we can "clone" into the canvas, we'll create the elements we need in the HTML to get a structure somewhat similar to what you've outlined in your question. This has the added advantage of being able to just change some of the CSS to also make changes in the canvas :
<div id="gradient">
<div class="text">COMPANY NAME</div>
<div class="h_bar"></div>
<div class="v_bar"></div>
</div>
It's just a container with an element for text, and one for each of the bars.
Some styling is neccessary as well, I'll do it the easy way, with position absolute and some really fast positioning, as these elements won't be visible unless someone has disabled javascript anyway :
#gradient {position: absolute;
background: #000;
top: 5%; left: 5%; right: 5%; bottom: 5%;
}
.text {position: absolute;
top: 20px;
left: 100px;
width: 400px;
color: #fff; font-size: 40px; font-weight: bold;
font-family: arial, verdana, sans-serif;
}
.h_bar {position: absolute;
height: 20px;
top: 100px; left: 60px; right: 60px;
background: #fff;
}
.v_bar {position: absolute;
width: 20px;
top: 140px; bottom: 30px; right: 60px;
background: #fff;
}
Without any javascript that would look exactly like THIS FIDDLE, and it should be somewhat responsive and adapt to the window size.
Now we need some javascript to turn those elements into something in a canvas. We'll create two canvas elements, one for the background, as I've decided to animate the background continously between random gradients, and one for the inner black box and the content (the text and the bars).
As the masking of the text and bars can be a little slow, we don't have to redraw everything, just the background canvas, as the foreground is pretty static.
This also avoids a flickering issue in some browsers with high frame rates, and we're going to use requestAnimationFrame for the animation of the background canvas, so flickering in the text mask would be an issue if we did'nt use two canvas elements.
For browsers that does'nt support requestAnimationFrame we'll add this polyfill to make sure it works everywhere.
Time to write some javascript, this of course uses jQuery :
var gradSite = {
init: function() {
var self = this;
self.create().setSizes().events();
(function animationloop(){
requestAnimationFrame(animationloop);
self.draw().colors.generate();
})();
},
create: function() { // creates the canvas elements
this.canvas = document.createElement('canvas');
this.canvas2 = document.createElement('canvas');
this.canvas.id = 'canvas1';
this.canvas2.id = 'canvas2';
this.canvas.style.position = 'absolute';
this.canvas2.style.position = 'absolute';
$('#gradient').after(this.canvas, this.canvas2);
return this;
},
events: function() { //event handlers
$(window).on('resize', this.setSizes);
$('#gradient').on('contentchange', this.draw2);
return this;
},
setSizes: function() { // sets sizes on load and resize
var self = gradSite,
w = $(window),
m = $('#gradient');
self.canvas.height = w.height();
self.canvas.width = w.width();
self.canvas2.bg = m.css('background-color');
self.canvas2.height = m.height();
self.canvas2.width = m.width();
self.canvas2.style.top = m.offset().top + 'px';
self.canvas2.style.left = m.offset().left + 'px';
self.draw2();
return self;
},
colors: {
colors: {
0: [255,255,0],
1: [255,170,0],
2: [255,0,0]
},
map: {
0: [0,0,1],
1: [0,1,1],
2: [0,1,1]
},
generate: function() { // generates the random colors
var self = this;
$.each(self.colors, function(i,color) {
$.each(color, function(j, c) {
var r = Math.random(),
r2 = Math.random(),
val = self.map[i][j] == 0 ? (c-(j+r)) : (c+(j+r2));
if (c > 255) self.map[i][j] = 0;
if (c < 0 ) self.map[i][j] = 1;
self.colors[i][j] = val;
});
});
}
},
raf: (function() { // polyfill for requestAnimationFrame
var lastTime = 0,
vendors = ['webkit', 'moz'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime(),
timeToCall = Math.max(0, 16 - (currTime - lastTime)),
id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}()),
calculateColor: function(colors) { // returns a rgb color from the array
return 'rgb(' + Math.round(colors[0]) + ',' + Math.round(colors[1]) + ',' + Math.round(colors[2]) + ')';
},
draw: function() { //draws the color background
var self = this,
c = self.canvas || document.getElementById('canvas1'),
ctx = c.getContext('2d'),
grad = ctx.createLinearGradient(0,0,0,self.canvas.height);
c.width = c.width;
grad.addColorStop(0, self.calculateColor(self.colors.colors[0]));
grad.addColorStop(0.5, self.calculateColor(self.colors.colors[1]));
grad.addColorStop(1, self.calculateColor(self.colors.colors[2]));
ctx.fillStyle = grad;
ctx.fillRect(0,0,self.canvas.width, self.canvas.height);
return self;
},
draw2: function() { // draws the black square and content
var self = this,
c = self.canvas2 || document.getElementById('canvas2'),
ctx2 = c.getContext('2d'),
txt = $('.text', '#gradient').first(),
hbar = $('.h_bar', '#gradient').first(),
vbar = $('.v_bar', '#gradient').first();
c.width = c.width;
ctx2.globalCompositeOperation = 'xor';
ctx2.font = txt.css('font');
ctx2.fillStyle = c.bg || '#000';
ctx2.fillText(txt.text(), txt.offset().left, txt.offset().top);
ctx2.fillRect(hbar.position().left, hbar.position().top, hbar.width(),hbar.height());
ctx2.fillRect(vbar.position().left, vbar.position().top, vbar.width(),vbar.height());
ctx2.fillRect(0,0,c.width,c.height);
}
}
The raf function would be the polyfill for requestAnimationFrame, and the two draw functions create the content in the canvas. It's really not that complicated.
We will call the above script inside a DOM ready handler, like so :
$(function() {
gradSite.init(); // starts the canvas stuff
});
Adding all that up into a fiddle, and adding a few elements for demonstration purposes, it would look like THIS FIDDLE, and here's the finished ->
FULL SCREEN DEMO
The only way I can see this working is if your black div has no background and is cut into sections that that each have a background. The company name area would need to have the same foreground color as the background for the rest of the div sections. Depending on your layout needs this might be fine.
For example, you could cut it into three sections and two images:
You can try combinig background-size and background-position with javascript:
setGradientSizes = function (el) {
var width = $(document).width() + 'px', height = $(document).height() + 'px';
$(el || '.gradient:not(body)').each(function () {
var offset = $(this).offset();
$(this).css('background-size', width + ' ' + height);
$(this).css('background-position', (offset.left * -1) + 'px ' + (offset.top * -1) + 'px');
})};
Working example here -> jsbin
NOTES:
this is not 100% cross browser - background-size is supported in FF4.0+, IE9.0+, Opera 10.0+, Chrome 1.0+, Safari 3+.
For some older browsers you can try browser specific prefixes (like -moz-background-size) - my example does not cover that.
To reduce load flickering you can apply calculations at first and then add background gradient
You could make the background of the image with the text black, then set the div's background color to rgba(0,0,0,0) making it transparent
This might be helpful for you according to my understanding
There is inherit to copy a certain value from a parent to its children, but there is no property the other way round (which would involve another selector to decide which style to revert).
You will have to revert style changes manually:
div { color: green; }
form div { color: red; }
form div div.content { color: green; }
If you have access to the markup, you can add several classes to style precisely what you need:
form div.sub { color: red; }
form div div.content { /* remains green */ }
Edit: The CSS Working Group is up to something:
div.content {
all: default;
}
If I was you I'll duplicate the css and jQuery, print it on a div on top of what ever and make the overflow hidden (like masking layers but with z-index).