I am trying to center-align text (that may or may not span several lines) within a <div> that has position: absolute applied to it.
Please consider the following markup:
<div class="item">
<img src="test.jpg" />
<div class="overlay">
Some long content
</div>
</div>
The CSS applied is as follows (please note that this is the LESS version):
.item {
position: relative;
img {
position: relative;
z-index: 1;
}
.overlay {
position: absolute;
z-index: 2;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(0,0,0,.5);
text-align: center;
a {
color: #fff;
}
}
}
As well as being center-aligned horizontally, I'd like for the text within .overlay to be vertically aligned to the middle. I've tried adding the following:
.item {
display: table;
.overlay {
display: table-cell;
vertical-align: middle;
}
}
I've also tried inline-block but nothing helps, since the element is absolutely positioned. I cannot use the usual line-height trick here, since the text may span several lines, and specifying a large line height will break the layout.
Does anyone know of a (relatively) cross-browser method to solve this issue? It needs to work in IE9+, FF and Chrome. If possible, I'd like to avoid adding any additional markup or 'divitis'.
I've put together a jsFiddle to demonstrate my issue (you'll also see the usual tricks work fine when the position != absolute):
jsFiddle Demo
Use a pseudo-element like :before and inline-block this way:
.item .overlay:before {
content:" ";
display:inline-block;
vertical-align:middle;
height:100%;
}
.item .overlay a {
display:inline-block;
vertical-align:middle;
color: #fff;
}
Check this Demo Fiddle
You may need to handle the space between those inline-block items HERE I use margin-right
Just make the absolute positioned element a "positioning" container, and put the actual element containers inside, like so - http://jsfiddle.net/Ggbtt/4/
HTML:
<div class="item">
<img src="http://placehold.it/350x150.jpg" />
<div class="overlay">
<div class="inner-container">
<div class="inner-cell">
Some long content
</div>
</div>
</div>
</div>
CSS:
.item {
position: relative;
width: 350px;
display: table;
}
.item .overlay {
position: absolute;
z-index: 2;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(0,0,0,.5);
text-align: center;
width: 100%;
height:100%;
vertical-align: middle;
}
.inner-container{
width: 100%;
height: 100%;
display:table;
}
.inner-cell {
display:table-cell;
vertical-align: middle;
text-align: center;
}
.item .overlay a {
color: #fff;
}
If using absolute position, I find this solution to work every time
.item .overlay{
top:50%;
-webkit-transform:translateY(-50%);
}
Related
I am having the following Issue:
I got a Website with a quite large DIV element, in which there is a img (sullsize).
As on the main index site, I want to have the "Site Title" called Palette within the DIV, not on the outside. Whenevery I try to do it with the Flex CSS, the Image will not go to the end (fill the element).
"My Team Site"
So my current issue is, I can't get the Palette Text into the item, and also I will be listing Photos and Jobdescriptions for the individuals, each has it's own flexbox, so it will behave right.
As said, I can't get them to be within the box.
The easyest way is if you look at my (Sample) Website:
LINK (it should look like on the main site. Maybee even with
Flex, instead of old-fashioned way)
Dashed Orange: Text Box
Dashed Red: Future Team Div (1 per Person)
This is the basic HTML and a part (ONLY A PART!) of the CSS, look at the Rest on the Website:
.content_item .content_title {
position: relative;
overflow: visible;
display: inline-block;
height: 100%;
width: 45%;
float: right;
flex-grow: 1;
flex-shrink: 1;
}
.content_item h2 {
position: absolute;
bottom: 0;
right: 0;
margin: 0;
padding-left: 20px;
width: 100px;
flex-grow: 1;
flex-shrink: 1;
color: rgba(255, 255, 255, .9);
white-space: nowrap;
letter-spacing: 1px;
font-size: 5em;
-ms-transform: rotate(270deg);
-webkit-transform: rotate(270deg);
transform: rotate(270deg);
}
<body>
<div class="site_palette">
<div class="header_div">
<h1 class="header_title">Schwarz & Torf Maler AG</h1>
<h3 class="header_subtitle">Wir Malen wo andere nur zuschauen</h3>
</div>
<div class="flex_container">
<a href="index.html">
<div class="content_item shadowbox_red">
<img src="http://maler1.calmarsolutions.ch/images/center_3.jpg" />
<div class="team_section">
<div class="team_part">
<img src="">
</div>
</div>
<div class="content_title">
<h2>Palette</h2>
</div>
</div>
</a>
</div>
</div>
</body>
The flex container is .content_item.
This container has three children (flex items):
img
div.team_section
div.content_title
Since these are three in-flow flex items, they respect each other's space and don't overlap.
The text you want to layer over the image is in an absolutely-positioned h2, which is a child of relatively-positioned .content-title.
What you need to do is add position: relative to the primary container, then apply position: absolute the non-image flex items.
Add this to your code:
.site_palette .content_item {
position: relative;
}
.team_section {
position: absolute;
}
/* adjustment below may be unnecessary */
.content_item .content_title {
/* position: relative; */
position: absolute;
right: 0;
}
.site_palette .content_item {
max-width: 70vw;
position: absolute;
}
.team_section {
display: flex;
position: absolute;
}
Locate the following code in your css:
.team_section {
display: flex;
}
And change it to:
.team_section {
display: none;
}
I have the following markup (Fiddle Example Here: http://jsfiddle.net/9gvj11o5/8/)
<div class="header">
<div class="image">
<img src="http://placehold.it/2200x800" alt=""/>
</div>
<div class="menu">This is the menu</div>
<div class="tools">These are the tools</div>
</div>
<div class="content">content</div>
And the following CSS:
.header {
position: relative;
}
.image {
position: absolute;
}
img {
width: 100%;
height: auto;
outline: 0;
}
I need the image to be responsive and have 100% width aligned to top.
But I also need the menu and tools to be over the image and having their normal flow.
Content should be after the image, so after the header.
The image would be the "background" of the header div. (I cannot use background-image)
I am using position but the menu and tools disappear the moment I use it.
What am I missing? Do I need another wrapper div somewhere?
I would wrap the 2 divs .menu & .tools so you need only to apply z-index to the wrapper div instead of each child. which make .menu & .tools (wrapped) in front of the .image.
then change position:absolute to position:relative to .image in order to have .content below header.
Below you can see the snippet, very lightweight.
.header {
position: relative;
}
.image {
position: relative;
z-index:1
}
#menu-all {
position:absolute;
top:0;
z-index:2
}
img {
width: 100%;
height: auto;
outline: 0;
}
<div class="header">
<div class="image">
<img src="http://placehold.it/2200x800" alt="" />
</div>
<div id="menu-all">
<div class="menu">This is the menu</div>
<div class="tools">These are the tools</div>
</div>
</div>
<div class="content">content</div>
You can use z-index to define the layer order of your elements. The smaller the number, the closer to the "bottom" of the stack. So we give the img a very small number, and menu and tools a very large one.
.header {
position: relative;
}
.image {
position: absolute;
z-index: 1; /* here you can use -1 as Paulie_D points out in the comments */
}
img {
width: 100%;
height: auto;
outline: 0;
z-index: 2; /* here you can use -1 as Paulie_D points out in the comments */
}
.menu {
position: absolute;
top: 0;
left: 0;
z-index: 888; /* You can remove this declaration entirely if you set -1 above */
}
.tools {
position: absolute;
top: 0;
right: 0;
z-index: 888; /* You can remove this declaration entirely if you set -1 above */
}
I tried to display vertical text exactly in center of div (navigation button) which is nested in floating element, I set size,magin:auto, vertical-align but text is on the edge against center.
Is there any other way to put the text where it should be without using absolute positioning?
<nav>
<div class="button"><p class="rotare">1st button</p></div>
<div class="button">1</div>
<div class="button">1</div>
<div class="button">1</div>
</nav>
nav {
width: 50px;
height: 600px;
background-color: red;
margin-left: 0px;
top:0px;
position: absolute;
display: inline-block;
float:left;
}
.button {
width: 50px;
height: 150px;
background-color: pink;
}
.rotare {
position: relative;
text-align: center;
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
background-color: white;
margin:auto;
vertical-align: middle;
width: 100px;
height: 20px;
}
You can do this with absolute positioning, but without having to manually push the content into its place by simply adding these rules to your existing css:
.button {
position: relative;
}
.rotare {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
Here's a JS Fiddle of it in action: http://jsfiddle.net/grammar/NgrWg/
And here's an article explaining this method of vertical centering in more detail: http://coding.smashingmagazine.com/2013/08/09/absolute-horizontal-vertical-centering-css/
EDIT - secondary approach without absolute positioning
Another approach is to use table and table-cell as the display property for the wrapper and text respectively. I've updated the fiddle to show that method as well: http://jsfiddle.net/grammar/NgrWg/1/.
Here's another article that explains this table-cell trick, and also outlines a third technique for centering things vertically: http://css-tricks.com/centering-in-the-unknown/
I initially had vertically centered text using the table/table-cell display method, which worked great. The problem came when I switched to a percentage height for the container and used a block level image (sibling to the text in question) to set the size of the container. I can no longer get the absolutely positioned text to equal the container height without declaring a static container size. Obviously this is simple to solve with JS, but I'd prefer not to go that route.
I'm also using picturefill.js to serve images, so using the image as a css background isn't an option (unless anyone has suggestions to make it work).
Here's the fiddle:
http://jsfiddle.net/rHZdQ/
And here's the code:
HTML
<div class="tile">
<a href="#">
<img src="#">
<div class="header-container">
<h2>title</h2>
</div>
</a>
</div>
CSS
.tile {
position: relative;
}
img {
display: block;
}
a {
display: block;
position: relative;
}
.header-container {
display: table;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
}
h2 {
display: table-cell;
text-align: center;
vertical-align: middle;
z-index: 199;
}
Centering Text in an Absolutely Positioned Image Overlay Using CSS
Consider the following HTML snippet:
<div class="tile">
<div class="image-container">
<img src="http://placekitten.com/400/400">
</div>
<div class="header-container">
<div class="panel">
<h2><span>percentage sized div</span></h2>
</div>
</div>
</div>
and apply the following CSS rules:
.tile {
border: 3px solid #555;
position: relative;
margin: 6px;
float: left;
}
.image-container img {
display: block;
height: 100%;
width: 100%;
}
.header-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.header-container .panel {
display: table;
width: 100%;
height: 100%;
}
.header-container .panel h2 {
display: table-cell;
vertical-align: middle;
text-align: center;
}
.header-container .panel h2 span {
display: inline-block;
padding: 5px;
border-radius: 5px;
background-color: rgba(255,255,255,0.5);
}
The parent/containing block is div.tile, and it has two child elements, .image-container which is in-flow, and .header-container which is absolutely positioned and hence out-of-flow.
Since .tile is floated, it shrinks-to-fit the content, which is the image in .image-container, with the dimensions determined by the native height and width of the image.
To create the overlay, .header-container is absolutely positioned to the top and left of its relatively positioned parent, with 100% width and height which forces it to extend to the containing block (see yellow outline).
Within .header-container, create an anonymous table by setting display: table to .panel, and specify 100% width and height so it extends and fills the .header-container.
Finally, define an anonymous table-cell on .panel's nested <h2> element, and apply text-align: center and vertical-align: middle to center the text post horizontally and vertically.
Note that the table-cell will extend the full width and height of the table so if you want to style the text with a border or background, you need to wrap it an inline-block element (the <span> in my example).
You can view the code at: jsFiddle Demo
Does your .header-container need to be width:100%? Can you use pixels instead?
If you use pixels and you do the following, then it will center it:
.header-container {
display: table;
height: 100%;
left: 50%;
position: absolute;
top: 0;
width: 400px;
margin-left:-200px;
}
Basically, margin-left has to be equal with half the width and a minus in fornt and then left:50%
UPDATE:
After informing me that it has to be only with percentage, the Jquery would be this:
$(document).ready(function() {
var minus = '-';
var headerwidth = $(".header-container").width();
$(".header-container").css('margin-left',minus+(headerwidth/2)+'px');
$(".header-container").css('left','50%');
});
I have a text area with id="aboutme" and an span with class="maxlength-feedback", I want the span to be positioned in the top-right-hand corner of the textarea. It will be a counter for the text area.
I know both elements should have position="relative" and the span should be display="inline-block", but it's not working.
I would appreciate any help. Thanks.
Just do it like this
Explanation: Wrap your textarea inside a container div and give position: relative; to the container, and position: absolute; to span, now to be sure your div default behavior which is display: block; will make your span flow on the extreme left so use display: inline-block; for your container div
Demo
HTML
<div class="wrap">
<textarea></textarea>
<span>Counter</span>
</div>
CSS
.wrap {
position: relative;
display: inline-block;
}
.wrap span {
position: absolute;
top: 0;
right: 0;
}
Html
<div>
<span class="mySpan">Some Text</span>
<textarea class="myTextArea"></textarea>
</div>
CSS
div{
position: relative;
float:left;
}
.mySpan{
position: absolute;
right: 0px;
}
Working Example: http://jsfiddle.net/VSWXs/
no, maxlength-feedback has to be absolute positioned, like this;
#aboutme {
position:relative;
}
.maxlength-feedback {
position:absolute;
right: 0; /* or so */
top: 0; /* or so */
}