Keep element always on screen with "position: sticky" - html

I have a container with known height (height is sometimes longer then screen).
This container has a vertically and horizontally centered element (via flex).
I was hoping to keep this element always on the screen vertically centered in the block in the visible portion of the container.
What I tried:
position:sticky; top:50% - however this only keeps it centered on the bottom half of container.
position:sticky; bottom:50% - however this only keeps it centered on top half
position:sticky; top: 50%; bottom:50%; - it seems top overrides bottom so this is just like my first try with top:50% only
I tried setting negative values but it didn't work
Here is a demo:
.container {
height: 1200px;
background-color: rgba(0, 0, 0, .7);
color: white;
display: flex;
justify-content: center;
align-items: center;
}
.center-piece {
background-color: green;
position: sticky;
top: 50%;
}
.center-piece2 {
background-color: steelblue;
position: sticky;
bottom: 50%;
}
<div class="container">
<div class="center-piece">
#1
</div>
<div class="center-piece2">
#2
</div>
</div>
Is there anyway to keep it perfectly centered, while "always on screen", in the visible porition of container, both top and bottom?
Here is a screencast of my application: https://www.youtube.com/watch?v=CwYaBgolNHU
The "rawr" will be the controls for the image behind it.

I may have misunderstood your question, but can you use:
position: fixed;
top: 50vh;
?
.container {
height: 1200px;
background-color: rgba(0, 0, 0, .7);
color: white;
display: flex;
justify-content: center;
align-items: center;
}
.center-piece {
background-color: green;
position: fixed;
top: 50vh;
left: 50vw;
transform: translate(-50%,50%);
}
<div class="container">
<div class="center-piece">#1</div>
</div>

NOTE: Compatibility varies across browsers..
According to caniuse.com, position: sticky is supported on current major browsers (Not IE).
jsFiddle
.container {
height: 1200px;
background-color: rgba(0, 0, 0, .7);
color: white;
display: flex;
justify-content: center;
align-items: center;
}
.center-piece {
background-color: green;
position: sticky;
top: 10px; /* 1 */
bottom: 50%;
left: 50%;
transform: translate(-50%,50%); /* 2 */
}
.center-piece2 {
background-color: steelblue;
position: sticky;
bottom: 10px; /* 3 */
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
<div class="container">
<div class="center-piece">#1</div>
<div class="center-piece2">#2</div>
</div>
NOTES:
position: sticky kicks in when element reaches top: 10px of viewport
How centering works with CSS positioning and transform properties
position: sticky kicks in when element reaches bottom: 10px of viewport

Related

make div center with water mark css

I want to put watermark-text at the center of page. but it's not work it always go to the left of page. I try to use top and left with the #background element but the font-size of #watermark-text get smaller how can I put #watermark-text in the center without change the font-size.
#background {
position: absolute;
background: white;
z-index: 0;
}
#content {
z-index: 1;
}
#watermark-text {
position: absolute;
color: #eae9e9;
font-weight: bold;
font-size: 800px;
}
<div id="background">
<p id="watermark-text">WaterMark</p>
</div>
<div id="content" </div>
I've used display: flex; align-items: center; justify-content: center; on the parent to center the child horizontally and vertically and in order to achieve that we need to set a height and a width to the parent.
#background {
height: 100vh;
width: 100%;
background: white;
display: flex;
align-items: center;
justify-content: center;
}
#content {
z-index: 1;
}
#watermark-text {
color: #eae9e9;
font-weight: bold;
font-size: 800px;
}
<div id="background">
<p id="watermark-text">WaterMark</p>
</div>
<div id="content"> </div>
If by watermark you mean text that overlays the screen with text then you can do it very simply by setting the body to position: relative. This means that when we set the background div with position: absolute and inset:0, the watermark is positioned relative to the body element. This makes the background div cover the whole page.
Use grid and place-items center to put the text in the center of the screen. I've coloured the background and set opacity on the text so you can see that it's overlaid the content.
Note: I've set the font size a percentage of the viewport width using the vw unit so as you make the screen bigger, the watermark increases in size to suit. You can set this to a pixel value or, even better, rem or em.
If you want the watermark not to move with the screen scroll, change position: absolute to position: fixed.
Any questions, just pop a comment in and I'll respond.
body {
position: relative;
margin: 0;
}
#background {
position: absolute;
inset: 0;
display: grid;
place-items: center;
color: #eae9e9;
background-color: rgba(0, 192, 0, 0.5);
opacity: 0.5;
font-weight: bold;
font-size: 15vw;
}
<div id="background">WaterMark</div>
<div id="content">
<img src='https://picsum.photos/id/237/400/900'>
</div>
#background {
position: fixed;
background: white;
width: 100vw;
height: 100vh;
top: 0px;
left: 0px;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
z-index: -10;
}
#content {
z-index: 10;
width: 100vw;
height: 100vh;
color: black;
}
#watermark-text {
color: #eae9e9;
font-weight: bold;
font-size: 800px;
}
<div id="background">
<p id="watermark-text">WaterMark</p>
</div>
<div id="content">jlsgdfjlgdsfjodfgjoifdgjasfddddddddddds<br>joiasjoidsajoasfds </div>
This is how I would do it looks strange in the editor but should work perfectly on the page, alternative you can just set a background to the div itself where to content is, be aware that this won't be secure as anyone can just change the HTML and CSS clientside anyway.
.watermark {
/* Used to position the watermark */
position: relative;
}
.watermark__inner {
/* Center the content */
align-items: center;
display: flex;
justify-content: center;
/* Absolute position */
left: 0px;
position: absolute;
top: 0px;
/* Take full size */
height: 100%;
width: 100%;
}
.watermark__body {
/* Text color */
color: rgba(0, 0, 0, 0.2);
/* Text styles */
font-size: 3rem;
font-weight: bold;
text-transform: uppercase;
/* Rotate the text */
transform: rotate(-45deg);
/* Disable the selection */
user-select: none;
}

Two Divs dependant on each other but they shouldn't

I'm pretty new to CSS so I was trying out some CSS-Battles just to learn some basics.
I was trying to get a circle with two mountains in it and had the idea to generate two divs, rotate them 45deg and then position them so they would match up with the picture needed.
For testing I painted the second mountain div black.
* {
margin: 0;
padding: 0;
}
.background {
align-items: center;
justify-content: center;
display: flex;
width: 100vw;
height: 100vh;
background-color: #293462;
}
.circle {
position: relative;
display: flex;
background-color: #FFF1C1;
width: 200px;
height: 200px;
border-radius: 50%;
overflow: hidden;
}
.mountain {
position: relative;
background-color: #FE5F55;
transform: rotate(45deg);
height: 200px;
width: 200px;
}
.mountain-1 {
background-color: #FE5F55;
top: 100px;
left: 41px;
}
.mountain-2 {
background-color: black;
top: 170px;
right: 70px
}
<div class="background">
<div class="circle">
<div class="mountain mountain-1">
</div>
<div class="mountain mountain-2">
</div>
</div>
</div>
Result
This was my first attempt. Then I noticed that when I set display of .mountain-1 to none the position of mountain-2 changes which I don't want and don't understand even after searching for solutions.
CSS changed
.mountain-1{
background-color: #FE5F55;
top: 100px;
left: 41px;
display: none;
}
Result
Also when I change the order of the two divs inside the HTML the result changes as well which in my mind makes not the most sense.
The main reason the two <div> elements are dependent on each other is because they both have the position CSS property set to relative. They inherit this from the parent element CSS .mountain.
This means the top, left, right, and bottom properties will be relative to other elements within the same container. To fix this, you need to set each mountain's position property to absolute. This means the position is set purely based on the values you use in top, left, right, or bottom. Also as a side note, if you do not have the parent element's position set to relative, using position: absolute will place the element based on the <body> element. So if you want the element's position to be based on the bounds of its parent, also set its parent's position to relative.
*{
margin: 0;
padding: 0;
}
.background{
align-items: center;
justify-content: center;
display: flex;
width: 100vw;
height: 100vh;
background-color: #293462;
}
.circle{
position:relative;
display: flex;
background-color: #FFF1C1;
width: 200px;
height: 200px;
border-radius: 50%;
overflow: hidden;
}
.mountain{
position: relative;
background-color: #FE5F55;
transform: rotate(45deg);
height: 200px;
width: 200px;
}
.mountain-1{
position: absolute;
top: 105px;
left: 40px;
}
.mountain-2{
position: absolute;
top:170px;
right: 70px
}
<div class="background">
<div class="circle">
<div class="mountain mountain-1">
</div>
<div class="mountain mountain-2">
</div>
</div>
</div>

Scroll does't work properly when aligning in the center of screen (using transform)

I'm trying to align a div in the center of the screen.
The code works great until I make the screen small, then the scrolling doesn't work properly and it cuts off the top of my centered component (when the centered component height becomes equal or less than screen size)
Any idea About a solution ?!
I'd be happy to use any other approach (without transform) but with none of the approaches I've accomplished to put the div in the center of screen)
.LoginContainer {
background-color: $base;
position: fixed;
top: 0px;
right: 0px;
bottom: 0px;
left: 0px;
width: 100%;
height: 100%;
overflow: scroll;
}
.LoginBox {
margin: 1rem;
padding: 5rem;
max-width: 30rem;
width: 60%;
position: relative;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
background-color: white;
}
<div class="LoginContainer">
<div class="LoginBox">
TEST
</div>
</div>
codesandbox.io/embed/suspicious-bird-hzood
I've also recreated the issue here. As you can see when the screen size has less height the white component gets clipped.
Image of the screen when the top part is clipped
Image of the regular screen
Would simply centering child components not work:
.LoginContainer {
background-color: $base;
...
display: flex;
justify-content: center;
align-items: center;
}
If you want the parent to be scrollable and the LoginComponent to be scrolled:
.LoginContainer {
background-color: $base;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.LoginBox {
padding: 15rem 5rem;
position: relative;
background-color: yellow;
}
<div class="LoginContainer">
<div class="LoginBox">
TEST
</div>
</div>
If you want the LoginComponent to not exceed the boundaries of the parent and make is scrollable:
.LoginContainer {
background-color: $base;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.LoginBox {
padding: 15rem 5rem;
position: relative;
background-color: yellow;
max-height: 100%;
overflow: auto;
}
<div class="LoginContainer">
<div class="LoginBox">
TEST
</div>
</div>

Using a css-filter on a child element to affect its parent

Is there any way of adding a filter (CSS or other type) to an element so this filter then effectively applies to the element below it.
I have an element with reduced opacity, that sits on top of a background image. I would like the element with reduced opacity to basically apply a black and white filter to the part of the element directly below it (effectively working as a mask). In the example below this means that the part of the image below the white box has the filter applied to it.
https://codepen.io/emilychews/pen/zWjWxo
Two things to note:
1) Because I'm using vh and vw units and the layout changes dependent on device / window size, I can't slice the image in photoshop or similar and then add or align it separately.
2) The image placeholder service I'm using serves up random images, and sometimes the image in the example is black and white - please don't let this confuse the issue.
body {
margin: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
width: 100%;
}
#row-1 {
position: relative;
width: 80vw;
height: 70vh;
background: red;
border: 1px solid black;
background-image: url("https://loremflickr.com/320/240");
background-size: cover;
}
#inner {
background: rgba(255, 255, 255, .8);
position: absolute;
width: 50%;
height: 40%;
right: 0;
top: 0;
padding: 1rem;
}
<div id="row-1">
<div id="inner">
<p id="text">Some Text</p>
</div>
</div>
Short answer - no. But there is a non-standard -webkit-back-drop filter that works in iOS, but it's only available in other browsers behind an experimental flag.
https://webdesign.tutsplus.com/tutorials/css-backdrop-filters--cms-27314
(SVG 1.1 had a mechanism to do this, but the spec was poorly written and only IE10+ ever implemented it (and they may have backed it out))
You can try mix-blend-mode
body {
margin: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
width: 100%;
}
#row-1 {
position: relative;
width: 80vw;
height: 70vh;
background: red;
border: 1px solid black;
background-image: url("https://loremflickr.com/320/240");
background-size: cover;
}
#inner {
background: rgba(255, 255, 255, .8);
position: absolute;
width: 50%;
height: 40%;
right: 0;
top: 0;
padding: 1rem;
mix-blend-mode: exclusion;
}
<div id="row-1">
<div id="inner">
<p id="text"></p>
</div>
</div>
Please, try this solution I have made on Codepen. You can play around with the Z-index & opacity in background-color.
It uses the :after pseudo element to make some sort of filter. Being stretched all over the div with an absolute position, everything underneath it will be affected.
I hope it can help you!
HTML:
<div class="box">
<p>Hello world!</p>
</div>
CSS:
.box {
position: relative;
width: 400px;
height: 300px;
background: url(http://farm2.staticflickr.com/1486/23990047223_5b7a0c82e8_b.jpg);
background-size: cover;
margin: 0 auto 100px;
z-index: 1;
}
.box:after {
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: block;
// change color opacity here!
background-color: rgba(0, 0, 0, 0.5);
}
// styling
.box p {
margin: 0;
font-size: 26px;
text-align: center;
color: white;
padding-top: 50px;
position: relative;
z-index: 0;
}

Position absolute div in center of screen view

I want to place div that has absolute position in center of the screen view (scrolled or not scrolled).
I have this but its places div in mid od the document and not mid of current view.
#main {
width: 140px;
height:100px;
border: 1px solid Black;
text-align: left;
position: absolute;
top: 50%;
left: 50%;
margin-left:-70px;
margin-top:-50px;
}
Use the following CSS:
.centered {
position: fixed;
top: 50%;
left: 50%;
/* bring your own prefixes */
transform: translate(-50%, -50%);
}
Change position:absolute to position: fixed and you should be good to go!
When you say position - absolute, the reference div is the parent div that has a position - relative. However if you say position -fixed, the reference is the browser's window. which is wat you want in your case.
In the case of IE6 i guess you have to use CSS Expression
If you don't want to change your element's position to fixed, here is a solution with keeping your element absolut.
Since CSS's calc() is supported by all browsers now, here a solution using calc().
#main {
width: 140px;
height:100px;
border: 1px solid Black;
text-align: left;
position: absolute;
top: calc(50vh - (/* height */100px / 2));
left: calc(50vw - (/* width */140px / 2));
}
A bit more complex way is to use multiple outer boxes. This method works well with or without hard coded width/height of the middle box (background colors added just to show what each box does):
/* content of this box will be centered horizontally */
.boxH
{
background-color: rgba(0, 127, 255, 0.2);
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: column;
align-items: center;
}
/* content of this box will be centered vertically */
.boxV
{
background-color: rgba(255, 0, 0, 0.2);
height: 100%;
display: flex;
flex-direction: row;
align-items: center;
}
/* content of this box will be centered horizontally and vertically */
.boxM
{
background-color: lightblue;
padding: 3em;
}
<div>
some text in the background
</div>
<div class="boxH">
<div class="boxV">
<div class="boxM">
this div is in the middle
</div>
</div>
</div>
https://jsfiddle.net/vanowm/7cj1775e/
If you want display div in the middle regardless of the scroll position, then change position to fixed
Here is a solution using margin and position: fixed :
#main{
width: 140px;
height:100px;
border: 1px solid black;
/* Centering #main on the screen */
position: fixed;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
It centers the div by increasing the margin on all sides to fit the whole screen.
EDIT: I found out there is a shorthand for top,right,bottom,left that is inset. It has been implemented in major browsers and you can see the compatibility on other browsers here
So to absolutely center a div on a screen:
#main{
width: 140px;
height:100px;
border: 1px solid black;
/* Centering #main on the screen */
position: fixed;
margin: auto;
inset: 0;
}
I managed to place absolutely positioned text in the center with the following:
position: absolute;
text-align: center;
left: 1%;
right: 1%;
This is a variation of the answer from Kenneth Bregat. It maintains absolute positioning rather than fixed, plus it solves text wrapping issues mentioned in some answers. Don't forget that the parent will need relative positioning.
What about this trick:
position: absolute;
height:200px;
top: 0;
left: 1%;
right: 1%;
margin-left: -half_of_the_div;
left: 50%;
position: fixed;
example on codepen