Summary of what I'm trying to achieve: I want to make my entire website in grayscale or saturation 0 and a div which follows the cursor to display the colors under that "mask" or div which acts like a mask.
I tried different approaches for this but I can't get it. I tried using CSS, with filter property or backdrop-filter. I tried finding the solution with Google Web Designer
In GWD the mask works just in one way, not like in photoshop.For example, in photoshop you can pun a top layer to remove the saturation than put a mask on it and reverse the mask to for it to apply outside the area created.
mask in pohotoshop
But in GoogleWebDesigner the mask is only applied on the area created, you can reverse it mask in googlewebdesigner
Do you have other suggestions how to approach this ? another method
This is possible using a combination of clip-path (documentation) and backdrop-filter (documentation). These are both quite new, so check whether they are suitable for you browser support requirements.
Most of the explanation is in the code comments, but a basic summary:
Fix an element over the entire document, and use backdrop-filter to make everything greyscale.
Use clip-path to only apply that filter to a rectangle in the center.
Use JS to offset the element so that the center remains over the cursor.
// This simply listens for mouse movenet and sets the CSS variables to the current X/Y
const cursor = document.querySelector(".cursor")
addEventListener('mousemove', e => {
cursor.style.setProperty("--x", `${e.pageX}px`);
cursor.style.setProperty("--y", `${e.pageY}px`);
});
/* This body style is just an example to make the demo work, it is not relevant to the solution*/
body {
min-height: 100%;
background-image: linear-gradient(45deg, #ff002f 10%, #2bcc33 10%, #2bcc33 20%, #0c12cc 20%, #0c12cc 30%, #0ddec6 30%, #0ddec6 40%, #d0db00 40%, #d0db00 50%, #ff002f 50%, #ff002f 60%, #2bcc33 60%, #2bcc33 70%, #0c12cc 70%, #0c12cc 80%, #0ddec6 80%, #0ddec6 90%, #d0db00 90%, #d0db00 100%);
background-size: 141.42px 141.42px;
}
/* This container covers the page and prevent the mask from blocking clicks or making the page scrollable*/
.cursorContainer {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
pointer-events: none;
}
.cursor {
/* These are set by JS and used to keep the box over the cursor */
--x: 0px;
--y: 0px;
/* These are each half of the box's width and height respectively */
--boxX: 60px;
--boxY: 40px;
/* These work out the boundries of the clip path from the sizes above */
--boxUpperX: calc(50% + var(--boxX));
--boxLowerX: calc(50% - var(--boxX));
--boxUpperY: calc(50% + var(--boxY));
--boxLowerY: calc(50% - var(--boxY));
position: fixed;
height: 200vh;
width: 200vw;
/* Use the variables above to keep this over the cursor */
left: calc(-100% + var(--x));
top: calc(-100% + var(--y));
/* Apply the greyscale filter to the webpage behind this element */
backdrop-filter: grayscale(1);
/* Only apply that filter to this area (Basically a thick rectangle with a gap for the colour to appear through) */
clip-path: polygon(0% 0%, 0% 100%, var(--boxLowerX) 100%, var(--boxLowerX) var(--boxLowerY), var(--boxUpperX) var(--boxLowerY), var(--boxUpperX) var(--boxUpperY), var(--boxLowerX) var(--boxUpperY), var(--boxLowerX) 100%, 100% 100%, 100% 0%);
}
<div class="cursorContainer">
<div class="cursor"></div>
</div>
Related
This question already has answers here:
Selecting and manipulating CSS pseudo-elements such as ::before and ::after using javascript (or jQuery)
(26 answers)
Closed 3 years ago.
I am loading two fixed body background-images, both set to cover. There is text extending below the page which scrolls; as well as top and bottom navigation icons. As expected, the second background covers the first and it looks like a normal, single loaded background.
In taking tips from previous questions, I have used body {} for the first (now hidden) background-image and body:after {} for the second (on-top, visible, and opacity adjustable) background-image.
I can use CSS body:after {opacity:.5} (or any other value 0->1) to achieve a single desired effect with the top background-image while keeping my text and navigation icons at full opacity. I, however, CAN NOT access the opacity value to change it. Once I am able to do so with the aid of someone more knowledgeable, I should then be able to move forward to dynamically increment a swap of values from 1->.9->.8->etc.->0 to disappear the top background-image using a timer with 11 frames and an appropriate time interval.
My successful code snippets are below along with my failed Javascript attempt at accessing the opacity value.
(P.S.: using #RickardElimää excellent ultimate answer, the top background starts out transparent and thus actually ends up as a fade-in.)
body {
background-image: url('./MyPhoto-1.jpg') ;
position: static; /* to work with Edge 10 */
/* z-index: -2 ; */
background-position: center center ;
background-repeat: no-repeat ;
background-attachment: fixed ;
background-size: cover ;
}
body:after {
content: " ";
top: 0;
left: 0;
bottom: 0;
right: 0;
background-image: url('./MyPhoto-2.jpg') ;
position: fixed ;
z-index: -2 ;
background-position: center center ;
background-repeat: no-repeat ;
background-attachment: fixed ;
background-size: cover ;
/* arbitrarily set immediately below and needing to be accessed via Javascript */
opacity: .4 ;
}
<script>//PROBLEM with scripting access to above opacity value
// document.body.getElementById("triedDivAndBodyTag").style.opacity = ".8"
document.getElementByID("body:after").style.opacity="0.8";
</script>
I would suggest using CSS variables, because you (for some apparent reason) can't access values of CSS properties through JavaScript. Also, try to use CSS animation as long as possibly because it's better optimized for it.
:root {
--background-opacity: 0.4;
}
body {
background-image: url('./MyPhoto-1.jpg') ;
position: static; /* to work with Edge 10 */
/* z-index: -2 ; */
background-position: center center ;
background-repeat: no-repeat ;
background-attachment: fixed ;
background-size: cover ;
}
body:after {
content: " ";
top: 0;
left: 0;
bottom: 0;
right: 0;
background-image: url('./MyPhoto-2.jpg') ;
position: fixed ;
z-index: -2 ;
background-position: center center ;
background-repeat: no-repeat ;
background-attachment: fixed ;
background-size: cover ;
opacity: var(--background-opacity);
transition: opacity 1100ms;
}
<script>
document.documentElement.style.setProperty('--background-opacity', 0.8);
</script>
I have three DIVs with the CSS "clip-path" attribute, which include low polygon shapes and text based titles.
I want to create divergent navigation (like a basic slider) between these DIVs and while titles are changing with a simple animation (fade-in and -out, etc.) shapes are transforming each other at same time.
Shapes will be static layers which change position when navigation is triggered. But titles are dynamically changing layers which are different for each DIV.
I had done this in a very simple way at first by assigning the "hover" state to the DIV, but since I do not know JS, I can only do this with "toggle", as you can see in the example.
But I want it to work with triggers like "click", "mousewheel" and the arrow keys.
Animations, transformations and other similar things about CSS are not a problem, I just have to learn how to create this navigation system between DIV's.
$('.toggle').click(function(e) {
e.preventDefault();
$('.container').toggleClass('moved');
})
.container {
background: #ccc;
margin: 2em auto;
width: 90%;
height: 0;
padding-top: 60%;
position: relative;
}
.poly {
background: rgba(255, 0, 0, 0.5);
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
transition: all .75s ease-in-out;
}
.poly:first-child {
clip-path: polygon(45% 25%, 40% 70%, 75% 30%);
}
.moved .poly:first-child {
clip-path: polygon(35% 50%, 55% 65%, 90% 45%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<button class="toggle">Move It</button>
<div class="container">
<div class="poly"></div>
</div>
Here is Jsfiddle file https://jsfiddle.net/Lsuw3L9z/
I have a background image I have sliced in Photoshop and set in a CSS class called".bd-image". I reference this class in the body element because I want it to be the background image for the whole page. I want each image to be 100% and not repeat. The problem is the images are on top of one another and not spreading out on the page. I changed the width and height from the absolute value to 100%, but no success. I need proper coding to set the images.
Does anyone know how to layer sliced images so they go down the page in the correct position and do not overlap? Or does anyone know of a sliced image background I can reference to get the correct coding?
.bd-image{
background:
url(images/orange-dark_01.jpg) 100% 46px no-repeat,
url(images/orange-dark_02.jpg) 100% 60px no-repeat,
.........
url(images/orange-dark_24.jpg) 100% 46px no-repeat;
}
</style>
</head>
<body class="bd-image" onload="StartTimers();" onmousemove="ResetTimers();">
When multiple images are added as background to an element, CSS would by default place them all in the same starting point. So, they will overlap one another. The background-position property should be used to set each image at their correct place. The value should be set such that the current image is offset from the previous image in X and/or Y directions.
In your case, since all images have to be 100% in width they can all start at X position = 0, only the Y position needs to be set. The Y position of second image would be height of first image, that of the 3rd image would be height of 1st + 2nd image and so on.
div {
/* as short-hand property */
background: url(http://lorempixel.com/400/100/nature/1) 0px 0px / 100% 46px no-repeat,
url(http://lorempixel.com/400/100/nature/2) 0px 46px / 100% 60px no-repeat,
url(http://lorempixel.com/500/100/nature/3) 0px 106px / 100% 46px no-repeat;
/* or as long-hand properties
background-image: url(http://lorempixel.com/100/100/nature/1), url(http://lorempixel.com/100/100/nature/2), url(http://lorempixel.com/100/100/nature/3);
background-repeat: no-repeat;
background-size: 100% 46px, 100% 60px, 100% 46px;
background-position: 0px 0px, 0px 46px, 0px 106px;*/
height: 152px;
width: 200px;
}
/* just for demo - hover to see responsiveness */
div {
transition: all 1s;
}
div:hover {
width: 400px;
}
<div></div>
Please look at this page
What I want to achieve is
and
Using following jQ function to dynamically resize div height based on document height
$(window).load(function() {
$('.sideBg').css({ 'height': ($(document).height())});
});
What am I missing?
Wouldn't it be better if you just used the background on the body? This way, you don't even need the additional elements or JavaScript.
body {
background: url(http://vefaestetik.az/design/img/bg/side_bg.png),
url(http://vefaestetik.az/design/img/bg/side_bg.png) 100% 0,
black radial-gradient(ellipse at center, #45484D 0%,black 100%);
background-repeat: repeat-y;
}
Don't forget to use background: black url(/design/img/bg/000.png); for the footer.
And don't forget that you should also have the prefixed versions
background: url(http://vefaestetik.az/design/img/bg/side_bg.png),
url(http://vefaestetik.az/design/img/bg/side_bg.png) 100% 0,
black -webkit-radial-gradient(center, ellipse cover, #45484D 0%,black 100%);
background: url(http://vefaestetik.az/design/img/bg/side_bg.png),
url(http://vefaestetik.az/design/img/bg/side_bg.png) 100% 0,
black -moz-radial-gradient(center, ellipse cover, #45484D 0%,black 100%);
background: url(http://vefaestetik.az/design/img/bg/side_bg.png),
url(http://vefaestetik.az/design/img/bg/side_bg.png) 100% 0,
black -o-radial-gradient(center, ellipse cover, #45484D 0%,black 100%);
before the unprefixed one in the styles for the body.
Works for me if I make these changes via Developer Tools
About compatibility: multiple backgrounds have better support than gradients (multiple backgrounds are supported by IE9, while CSS gradients are not). Actually, this won't work in IE 9 precisely because of the gradient. However, you can make it work in IE9 without the gradient by adding before all the prefixed versions a multiple background fallback (without the gradient).
background: url(http://vefaestetik.az/design/img/bg/side_bg.png),
black url(http://vefaestetik.az/design/img/bg/side_bg.png) 100% 0;
you need to remove the margin-top that is on your .wrapper <div> for the top to be fixed:
.wrapper {
background: url("/design/img/wrapper-bg.png") no-repeat center top;
margin-bottom: 0 !important;
margin-left: auto;
margin-right: auto;
/*margin-top: 20px; remove this */
padding-top: 120px;
position: relative;
width: 1020px;
}
Then for the bottom part i would suggest to get the height of the .wrapper <div>:
$(function() {
var wrapperHeight = $('.wrapper').height();
$('.sideBg').css('height': +wrapperHeight+'px');
});
If you are facing unnecessary padding always use a reset.css file.
Copy the code from here: http://meyerweb.com/eric/tools/css/reset/
I have a page that looks like this
-----------------------------------
| ************* |
| ************* |
| ************* |
| ************* |
| ************* |
| ************* |
-----------------------------------
The outer frame is the browser edge and thus the <body>, and the stars are a centred background image on the <body> element.
Now, using javascript I'd like to add some aboslutely positioned DIVs each side of that background in order to extend it:
-----------------------------------
|*********|*************|*********|
|*********|*************|*********|
|*********|*************|*********|
|*********|*************|*********|
|*********|*************|*********|
|*********|*************|*********|
-----------------------------------
As the window is resized the centred background will move (to remain in the center of the window), so the divs on each side should move in consequence.
Can anyone please suggest an approach to solving this issue?
Side note on why I'm doing this:
The background is large image, and I wish to have it repeated across the screen by flipping it as described here:
Background flipped tiling using Javascript
The actual process of flipping was discussed in that question, whereas this question deals with the CSS/Javascript aspect of positioning.
Note that in the case of non-capable browsers I'm happy leave the page as it is in the first diagram, with only the centred background.
Add the two DIVs using javascript. Than set their positions as you wish in relation to the centre of the screen. Than add an onresize event which will reposition DIVs when the browser window gets resized.
window.onresize = updateDivsPosition;
You can try a pure css solution using positioning. I am assuming that you have a fixed-size image in the centre of the page. For example's sake let's say your image is 800px wide, then
Position the left div with left 0px, right 50% and add a right margin
of 400px
Position the right div with left 50%, right 0px and add a
left margin of 400px
Example: http://jsfiddle.net/F4kay/
(note that I have assumed a smaller image width 256px for the smaller jsfiddle window)
CSS:
#left {
position:absolute;
left:0px;
right:50%;
top:0px;
bottom:0px;
margin-right: 128px; /* image width / 2 */
background-color:#ccc;
}
#right {
position:absolute;
left:50%;
right:0px;
top:0px;
bottom:0px;
margin-left: 128px; /* Image width / 2 */
background-color:#ccc;
}
HTML:
<div id="left">Left</div>
<div id="right">Right</div>
As for the height of these divs, it's up to you how you deal with this, either top / bottom: 0px or a fixed/percentage height. In the example I have used top 0px and bottom 0px.
The trick is to basically add 2 divs, one which takes up the left half of the screen and another which takes up the right. You add a margin to the inner div edges to reveal the inner contents. I have assumed a fixed width but you could also use half of a percentage width. If your image changes dynamically with js it's just a case of updating the margins.
For completeness, I've included a full example using this technique. I think it's a clean solution.
Example: http://jsfiddle.net/Hqpyx/
CSS:
body, .bgImage {
background-image: url('http://flickholdr.com/640/1280/5');
}
.flip {
-moz-transform: scaleX(-1);
-o-transform: scaleX(-1);
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
filter: FlipH;
-ms-filter: "FlipH";
}
body {
background-position: top center;
}
#left {
position:absolute;
left:0px;
right:50%;
top:0px;
bottom:0px;
margin-right: 320px; /* image width / 2 */
background-position:top left;
}
#right {
position:absolute;
left:49.99%;
right:0px;
top:0px;
bottom:0px;
margin-left: 320px; /* Image width / 2 */
background-position:top right;
}
HTML:
<div id="left" class="bgImage flip"></div>
<div id="right" class="bgImage flip"></div>
Personally I would avoid flipping the image like this. Unless you have some restriction you could just edit your background image and splice half and half of a flipped version together like
[ ] = full image
{ } = flipped image
create an image that looks like
}[ ]{
Here's my static CSS solution. It's similar to Matt's answer but I couldn't get his to work with flipped images and flexible width.
Demo here.
So far it only adds a single div on each side. If you need more, I could write some JS for that. The HTML markup of the page is:
<div class="content">
<div class="left-background"></div>
<div class="right-background"></div>
content
</div>
and CSS:
body {
color: #dddddd;
overflow-x: hidden;
}
#media (max-width: 400px) {
body {
overflow-x: visible;
}
.left-background, .right-background {
display: none;
}
}
.content, .left-background, .right-background {
background-image: url(http://flickholdr.com/400/300/sea,sun/bw);
height: 200px;
width: 400px;
}
.left-background, .right-background {
-moz-transform: scaleX(-1);
-o-transform: scaleX(-1);
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
filter: FlipH;
-ms-filter: "FlipH";
position: absolute;
}
.left-background {
left: -400px;
}
.right-background {
right: -400px;
}
.content {
margin: 0 auto;
position: relative;
}