Vertical aligning content in :before pseudoelement - html

I'm trying to create an overlay on some links that will show a magnifying glass as an overlay when you hover over it.
For simplicity, I've created a fiddle here: https://jsfiddle.net/rw4hngvj/1/
I'm able to get the magnifying glass icon centered horizontally, but I can't center it vertically, it's always at the top of the element. I've tried setting vertical-align:middle and top:50%, but neither of those work.
One restriction I have is that I can't change the HTML at all, and I can only change the css for the :before pseudoelement.
Is there any way I can center the content of :before?

Add position:relative; to .caption:before.
You need to use the position property along with top.

Adding these properties to your :before element, should center it. (based on your current code) Explanation below.
transform: translateY(-50%);
position: absolute;
left: 0;
right: 0;
Position: absolute is KEY.
Using a combination of position:absolute, left: 0, right: 0, and margin: 0 auto (this is like saying: margin-left: auto, margin-right: auto, margin-top/bottom: 0) centers your element horizontally.
And using position: absolute, top: 50%, transform: translateY(-50%) centers your element vertically.
There are other ways to do this, but this is the quickest way that requires no modification to your current CSS.
Your final css for caption:before should look like this:
.caption:before {
content: "\f002";
font-family: 'FontAwesome';
color: #ffffff;
font-size: 2em;
top: 50%;
margin: 0 auto;
display: block;
transform: translateY(-50%);
position: absolute;
left: 0;
right: 0;
}

add position .caption:before
.caption:before {
content: "\f002";
font-family: 'FontAwesome';
color: #ffffff;
font-size: 2em;
/* vertical-align: middle; */
top: 50%;
left:50%;
margin: -16px 0 0 -16px;
display: block;
position: absolute;
}
https://jsfiddle.net/rw4hngvj/3/

a.tile
{
position: relative;
display: block;
width: 150px;
height: 150px;
background-color: green;
}
.caption
{
width: 100%;
height: 100%;
opacity: 0;
display: block;
background: rgba(0,0,0,.6);
text-align: center;
cursor: pointer;
}
.caption:hover {
opacity: 1;
}
.caption:before {
content: "\f002";
font-family: 'FontAwesome';
color: #ffffff;
font-size: 2em;
top: 0; left: 0; bottom: 0; right: 0;
display: block;
width: 1em;
height: 1em;
overflow: auto;
margin: auto;
position: absolute;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">
<a class="tile">
<div class="caption">
</div>
</a>
<a class="tile">
<div class="caption">
</div>
</a>

If you can use flexbox, just try this one
.caption
{
width: 100%;
height: 100%;
display: flex;
justify-content:center;
flex-direction:both;
align-items:center;
opacity: 0;
background: rgba(0,0,0,.6);
text-align: center;
cursor: pointer;
}

Related

create multiple pseudo elements in the same container

In this way, the last statement will be the only one visible due to the css cascade.
Isn't there an alternative way to have all three pseudo-elements in the same container?
div class="container"</div>
.container {
position: relative;
}
.container:after {
position: absolute;
content: "some text";
top: 10%;
left: 20%;
}
.container:after {
position: absolute;
content: "";
border: 5px solid yellow;
width: 50%;
top: 10%;
left: 20%;
}
.container:after {
position: absolute;
content: "";
border: 5px solid blue;
width: 60%;
top: 30%;
left: 50%;
}
As it is not possible to have multiple before or after pseudo elements on one element, this snippet takes a different approach to placing the yellow and blue underlines.
They are drawn using CSS background-image with two linear-gradients on one pseudo element. Each is sized and positioned appropriately.
The snippet produces this:
body {
width: 100vw;
display: flex;
justify-content: center;
}
.container {
--h: 0.5em;
/* set this to the height of each underline */
font-family: sans-serif;
font-size: 36px;
text-align: center;
position: relative;
display: inline-block;
}
.container::before {
content: '';
position: absolute;
width: 300%;
height: 2em;
left: 50%;
transform: translateX(-50%);
background-image: linear-gradient(#ffff66, #ffff66), linear-gradient(cornflowerblue, cornflowerblue);
background-size: 95% var(--h);
background-position: left 0.75em, right 1em;
background-repeat: no-repeat;
z-index: -1;
}
<div class="container">Some text</div>
Obviously you will want to set the various dimensions to suit your particular case.

Center a picture on top of another picture using position absolute

I'm trying to put two different things on top of an image inside a media object from bootstrap. One of them is a badge/label which should be placed on the bottom right corner of the image, but currently I can only get it to appear on the top left. The other is a play icon, which should appear smack bang in the middle of the image.
Here is the code, and also a jsfiddle:
HTML:
<a class="news-link" href="#">
<div class="media">
<div class="image-container">
<img class="pull-left img-responsive" src="http://i59.tinypic.com/16m9f1f.png">
<div class="video-badge">
<h6>Badge</h6>
</div>
<div class="play-icon">
<img class="img-responsive" src="http://i57.tinypic.com/20jptok.png">
</div>
</div>
<div class="media-body">
<h4 class="media-heading">Title</h4>
Content
</div>
</div>
</a>
CSS (as well as some others and Bootstrap which I put on the jsfiddle):
.image-container {
position: relative;
}
.image-container img {
padding-right: 10px;
}
.video-badge {
position: absolute;
top: 0;
left: 0;
display: inline-block;
padding: 5px 25px 5px 10px;
overflow: hidden;
z-index: 1;
}
.video-badge h6 {
text-decoration: none;
color: #fafafa;
margin: 0;
}
.video-badge:after {
content: '';
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background: #5e4c33;
-webkit-transform-origin: 100% 0;
-ms-transform-origin: 100% 0;
transform-origin: 100% 0;
-webkit-transform: skew(-25deg);
-ms-transform: skew(-25deg);
transform: skew(-25deg);
z-index: -1;
}
.play-icon {
position: absolute;
top: 0;
left: 0;
display: inline-block;
padding: 5px 25px 5px 10px;
overflow: hidden;
z-index: 1;
max-width: 85px;
}
JSFiddle:
http://jsfiddle.net/pgo7h903/
Change your css like this
CSS Code:
.image-container {
display: inline-block;
float: left;
}
.play-icon {
display: inline-block;
left: 0;
margin: 0 auto;
max-width: 85px;
overflow: hidden;
padding: 75px 25px 5px 10px;
position: absolute;
right: 0;
top: 0;
z-index: 1;
}
.video-badge {
bottom: 0;
display: inline-block;
left: 0;
overflow: hidden;
padding: 5px 25px 5px 10px;
position: absolute;
z-index: 1;
}
.media img.pull-left.img-responsive {
max-width: 100%;
}
see demo http://jsfiddle.net/JentiDabhi/65ajj56j/4/
#JentiDabhi 's answer works but isn't an efficient way to code, as it uses up a lot of code. Try this:
.play-icon {
width: auto;
margin: 65px;
}
Add that into your CSS and it should center it. If you feel it's not centered, change the margin to margin-right and margin-top and change it there.
EDIT
For the badge, add this:
.video-badge {
margin-left: 201px;
margin-top: 143px;
}
Now it should be at the bottom right of the image.

CSS - Separator with text in middle

I need to create a separator with text in the middle. By middle I mean both centered horizontally and vertically - there are many examples of this technique using pseudo elements or an extra span in the middle.
Here's some code I would normally use - uses the span method:
h2.centre-line
{
width:40%;
text-align:center;
border-bottom:0.1rem solid #ccc;
line-height:0.1em;
margin:2.5rem 30%;
}
h2.centre-line span
{
background-color:#fff;
padding:0 1rem;
}
<h2 class="centre-line"><span>Text</span></h2>
The problem I have with all of the examples I have found so far is that the text is on a transparent background with margin spacing around it. However what I want to do is place the text in a container with height and keep it centered, like this:
At the moment I've been unable to adapt my code sucessfully and not come across any further suitable examples to follow.
Any ideas?
Your request is a little unclear as it's not stated what this 'separator' is supposed to be separating.
However, vertical & horizontal centering can be achieved by using absolute positioning.
The 'line behind' is achieved by a pseduo-element.
* {
margin: 0;
padding: 0;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.wrap {
height: 200px;
position: relative;
background: lightgrey;
margin: 5px;
}
h2.centre-line {
text-align: center;
position: absolute;
top: 50%;
left: 50%;
width: 40%;
transform: translate(-50%, -50%);
}
h2.centre-line:before {
content: "";
position: absolute;
width: 100%;
height: 1px;
top: 50%;
left: 0;
z-index: -1;
background: red;
}
h2.centre-line span {
background-color: lightblue;
padding: 1rem;
display: inline-block;
}
<div class="wrap">
<h2 class="centre-line"><span>Text</span></h2>
</div>
JSfiddle Demo with another wrapper with greater height.
Use an hr? something like this: http://liveweave.com/42IlZQ
hr {
padding: 0;
border: none;
border-top: medium double #333;
color: #333;
text-align: center;
}
hr:after {
content: "ยง";
display: inline-block;
position: relative;
top: -0.7em;
font-size: 1.5em;
padding: 0 0.25em;
background: white;
}
<div class="container">
<hr class="hr-text" data-content="AND">
</div>
<style type="text/css">
.container {
max-width: 50%;
margin: 40px auto;
}
.hr-text {
line-height: 1em;
position: relative;
outline: 0;
border: 0;
color: black;
text-align: center;
height: 1.5em;
opacity: .5;
}
.hr-text:before {
content: '';
background: linear-gradient(to right, transparent, #818078, transparent);
position: absolute;
left: 0;
top: 50%;
width: 100%;
height: 1px;
}
.hr-text:after {
content: attr(data-content);
position: relative;
display: inline-block;
color: black;
padding: 0 .5em;
line-height: 1.5em;
color: #818078;
background-color: #fcfcfa;`enter code here`
}
</style>`enter code here`

CSS: margin auto and position absolute

I'm trying to create a "button" with 2 sections (each is 50% of the height of the div) separated by an horizontal bar. Each of the sections has centered text. The size of the button is going to be manipulated using javascript, and I'm trying to avoid also using javascript to position the elements inside the "button".
What I have so far is http://jsfiddle.net/u5u7d31p/2/, but i'm having a problem centering the horizontal bar. If I change the position of the separator to relative, the bar is centered, but then it changes the position of the bottom part of the text. I can also change the margin to a static value (margin: 0 63px;) to center it, but I would like to avoid it if there is an easier solution that doesn't require javascript.
.img_overlay .separator{
position: absolute;
top: -1px;
left: 0;
height: 3px;
width: 70px;
margin: 0 auto;
background: #444;
}
Any ideas? Thanks.
All codes are ok. Just put this css below to .img_overlay .separator class.
Full code is below:
.img_overlay .separator {
position: absolute;
top: -1px;
left: 0;
height: 3px;
width: 70px;
margin: 0 auto;
background: #444;
right: 0;
}
view my demo on jsfiddle
.img{
float: left;
background-repeat:no-repeat;
background-size:100% 100%;
border-radius: 4px;
width: 200px;
height: 51px;
background: red;
overflow: hidden;
}
.img_overlay{
width: 100%;
height: 100%;
background: #222;
color: #ddd;
position: relative;
opacity: 0.8;
}
.img_overlay>div{
display: block;
width: 100%;
height: 50%;
text-align: center;
position: relative;
}
.img_overlay .middle{
position: relative;
top: 50%;
transform: translateY(-50%);
}
.img_overlay .separator{
height: 3px;
width: 70px;
margin: 0 auto;
background: #444;
}
<div class="img">
<div class="img_overlay">
<div class="img_show_details">
<div class="middle">details</div>
</div>
<div class="img_open">
<div class="separator"></div>
<div class="middle">open</div>
</div>
</div>
</div>
All I did was taking off :
.img_overlay .separator{
position: absolute;
top: -1px;
left: 0;
}
This following fix works okay in firefox and chrome but mess in IE.
I fixed height in div, top in middle and top in separator
.img_overlay>div {
display: block;
width: 100%;
height: 40%;
text-align: center;
position: relative;
}
.img_overlay .middle {
position: relative;
top: 60%;
transform: translateY(-50%);
}
.img_overlay .separator {
position: relative;
top: 5px;
left: 0;
height: 3px;
width: 70px;
margin: 0 auto;
background: #444;
}
here's the demo in jsfiddle.

How to center a child div with a smaller parent div

I have a div (fixed) which acts like a pop up:
<body>
<div class="popup-container">
<div class="popup-item">
Yolowing
</div>
</div>
</body>
This css allows the container to be horizontally centered (having a 100% width makes everything behind it unclickable; thus, I set it to 1px):
.popup-container {
position: fixed;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
width: 1px;
z-index: 9999;
}
.popup-item {
display: block;
min-width: 20px;
padding: 25px 50px;
background-color: yellow;
}
However, I am unable to center .popup-item due to the parent element .popup-container being smaller than its child. How do I center .popup-item while still being able to click it (pointer-events: none entirely disabled it)?
Vote to Close almost has it, but with the 1px width, the element doesn't get centered.
Do this instead:
.popup-container {
position: fixed;
left: 0;
right: 0;
z-index: 9999;
text-align:center;
height:0px;
}
.popup-item {
display: inline-block;
min-width: 20px;
padding: 25px 50px;
background-color: yellow;
}
This will make it centered, because the container is 100% wide. However, pointer-events:none; will allow you to click through to anything below it.
A couple of solutions.
First, you can make the child of the container centered using translateX() transform: http://jsfiddle.net/Yjz5R/. The same effect can be accomplished using negative margins, but the width for the container's child has to be set: http://jsfiddle.net/9Qmza/.
CSS:
.popup-item {
position: absolute;
min-width: 20px;
padding: 25px 50px;
background-color: yellow;
top: 0;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
}
Or second, you can make the container "immune" to click events:
Markup:
<input type = "checkbox" id = "clickToggle" />
<label for = "clickToggle">Click me</label>
<div class="popup-container">
<div class="popup-item">
Yolowing
</div>
</div>
Styles: http://jsfiddle.net/CVfHt/.
.popup-container {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: rgba(200, 200, 200, 0.5);
pointer-events: none;
}
.popup-item {
position: absolute;
min-width: 20px;
padding: 25px 50px;
background-color: yellow;
top: 50%;
left: 50%;
-webkit-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
pointer-events: all;
}
input[type = "checkbox"] {
display: none;
}
input[type = "checkbox"] + label {
cursor: pointer;
}
input[type = "checkbox"]:checked ~ div {
display: none;
}
Lastly, a question/comment. If you do not want the container to be visible, then why use it at all? Just keep the markup of the child and get rid of the container: http://jsfiddle.net/yvc4E/.
.popup-container {
position: fixed;
left: 0;
right: 0;
margin-left: auto; /* remove this line - unnecessary*/
margin-right: auto; /* and this line, remove */
width: 1px;
z-index: 9999;
text-align: center; /* add this */
}
.popup-item {
display: inline-block; /* change to inline-block */
min-width: 20px;
padding: 25px 50px;
background-color: yellow;
}