Css Left property issue - html

Using the left property in #image-list>.image-container>p seems to center the <p> element in the div with id #image-list and not its parent. I do not understand what I did wrong.
btn.onclick = e => {
list = document.getElementById("image-list");
item = list.children[0];
item = item.cloneNode(true);
document.getElementById("image-list").appendChild(item);
}
#image-list {
display: flex;
gap: 4vmin;
position: absolute;
left: 50%;
top: 50%;
transform: translate(0%, -50%);
}
#image-list>.image-container>.image {
width: 40vmin;
height: 56vmin;
object-fit: cover;
object-position: 100% center;
}
#image-list>.image-container>p {
position: absolute;
color: white;
top: 25%;
left: 50%;
transform: translate(-50%, -50%);
display: block;
font-family: Times New Roman;
font-size: 2rem;
-webkit-text-stroke: 0.5px black;
}
#image-list>.image-container {
text-align: center;
position:relative;
}
<div id="image-list">
<div class="image-container">
<p>hello world</p>
<img class="image" src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/800px-Image_created_with_a_mobile_phone.png" draggable="false">
</div>
</div>
<button id="btn">add image</button>

To center the <p> element within its parent, which is .image-container, you can add position: relative to .image-container and set left: 50% and transform: translateX(-50%) on #image-list > .image-container > p.
try this example :
#image-list>.image-container {
text-align: center;
position: relative;
}
#image-list>.image-container>p {
position: absolute;
color: white;
top: 25%;
left: 50%;
transform: translateX(-50%);
display: block;
font-family: Times New Roman;
font-size: 2rem;
-webkit-text-stroke: 0.5px black;
}

Absolute positioning is with respect to the edges of the closest positioned ancestor.
"positioned" means "has a position property that is not static.
You haven't set the position property of .image-container, so it has the default value, which is static.
#image-list has position: absolute so it is the closest positioned ancestor so your positioning is done with respect to that element's edges.

The issue is with the left property used in the #image-list > .image-container > p selector. The left property is positioning the element relative to its positioned parent, which is .image-container in this case. Since .image-container doesn't have a specific left property defined, it defaults to 0.
However, the desired effect is to center the element relative to #image-list. To achieve this, you can add position: relative to the #image-list selector, which will make it the positioned parent of .image-container and the element. Then, you can use left: 50% and transform: translateX(-50%) on the element to horizontally center it within #image-list.
Here's the updated CSS:
#image-list {
display: flex;
gap: 4vmin;
position: absolute;
left: 50%;
top: 50%;
transform: translate(0%, -50%);
position: relative; /* added */
}
#image-list > .image-container > p {
position: absolute;
color: white;
top: 25%;
left: 50%;
transform: translateX(-50%); /* updated */
display: block;
font-family: Times New Roman;
font-size: 2rem;
-webkit-text-stroke: 0.5px black;
}
With these changes, the element should be centered horizontally within #image-list.

Related

Trying to center text over image HTML [duplicate]

This question already has answers here:
Absolute position is not working
(6 answers)
Closed 10 months ago.
Trying to center text over image in HTML, but my method keeps pushing the text to the very beginning of the page at the top. My method is below...
.info {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.map-p {
font-size: 27pt;
text-align: center;
color: black;
position: relative;
z-index: 1;
}
<div class="map-section">
<img id="map" src="https://img.freepik.com/free-photo/europe-map-pins-travel-your-planning-trip_255544-1467.jpg?w=2000" alt="Image cannot be displayed" />
<div class="info">
<p class="map-p">We have locations all over!</p>
</div>
</div>
because .map-section needs to have position: relative
long answer:
in order for position absolute to use the reference of the parent. the parent needs to have position: relative
so adding
.map-section: { position: relative };
and fix the transform, should be
transform: translate(50%, -50%);
will get what you want
Two things:
1.) Set position: relative to the parent element (.map-section) to make it the reference for the absolutely positioned element.
2.) (optionally?) Limit the size of your image to its container's width and add height: auto to keep the proportion:
#map {
width: 100%;
height: auto;
}
.map-section {
position: relative;
}
.info {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.map-p {
font-size: 27pt;
text-align: center;
color: black;
position: relative;
z-index: 1;
}
<div class="map-section">
<img id="map" src="https://img.freepik.com/free-photo/europe-map-pins-travel-your-planning-trip_255544-1467.jpg?w=2000" alt="Image cannot be displayed" />
<div class="info">
<p class="map-p">We have locations all over!</p>
</div>
</div>
It should be like that
For more info : https://www.w3schools.com/css/css_positioning.asp
.info {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.map-p {
font-size: 27pt;
color: black;
position: relative;
z-index: 1;
}
.map-section{
position: relative;
}

Left align text in full width div

I am attempting to left align text in a div that takes the full width of it's parent.
This is the structure of one of several links created using Angular's Flex Layout.
<div class="container" fxLayout fxLayoutAlign="center" fxLayoutGap="10px">
<a mat-flat-button color="primary" fxFlex href="https://example.com/">
<div class="hoverOff"><fa-icon [icon]="faToolbox"></fa-icon>Broken</div>
<div class="hoverOn">
<div class="text">
Is your request causing an impact to a business-critical function, which is impacting daily production?
</div>
</div>
</a>
......
</div>
Without hovering, the .hoverOff element is visible. During hover, the .hoverOn element slides over the .hoverOff element.
.hoverOn uses position: absolute to stay hidden until hover.
Adding text-align: left to .text left aligns the text like I want but it's on the left edge of the div and not in the center with margins like I would like.
I have created an example for this and the CSS is below.
a {
color: white !important;
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
a .hoverOn {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background-color: #00539b;
overflow: hidden;
height: 0;
border-radius: 4px;
width: 99%; /* Prevents flicker on bottom corners */
margin: 0 auto; /* Centers div for new width */
transition: 0.25s cubic-bezier(0.4, 0, 0.2, 1); /* Material's Standard easing */
}
.text {
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
position: relative;
padding: 5px;
text-align: left;
}
a:hover .hoverOn {
height: 100%;
}
How can I solve this?

How can I get an h1 element to display over an image?

I want to display my page's title, "Math Achievement Tutoring", over a photograph of a hiker. My first attempt was to create this html:
<div id="wrapper">
<header>
<h1>Math Achivement Tutoring</h1>
</header>
<div id="hero">
<img src="http://michaelmossey.com/demo/home-hiker-grayish.jpg" alt="" width="500">
</div>
</div>
with this CSS, the idea being to position the h1 as absolute:
h1 {
text-align:center;
position: absolute;
color: #a04040;
}
but this means the title is no longer centered. I may run into other trouble as well if I start to fiddle with margin and padding.
h1 {
text-align:center;
position: absolute;
color: #a04040;
}
<div id="wrapper">
<header>
<h1>Math Achivement Tutoring</h1>
</header>
<div id="hero">
<img src="http://michaelmossey.com/demo/home-hiker-grayish.jpg" alt="" width="500">
</div>
</div>
What are my options for achieving this, and does it depend on where I want to take this website eventually? (like adding a navigation menu below the image)? Is there any simple demonstration code?
First, add position relative to #wrapper, then :
if you want it to be vertically & horizontally centered
h1 {
text-align:center;
position: absolute;
color: #a04040;
left: 50%;
top: 50%;
transform: translate( -50%, -50% );
}
if you want it to be vertically centered
h1 {
text-align:center;
position: absolute;
color: #a04040;
top: 50%;
transform: translateY( -50% );
}
if you want it to be horizontally centered
h1 {
text-align:center;
position: absolute;
color: #a04040;
left: 50%;
transform: translateX( -50% );
}
Just as Loesh Gupta says: make the wrapper .wrapper { position: relative; }. To center the text you can use multiple options. I'd go with something like this:
h1 { position: absolute; left: 50%; right: 50%; transform: translate(-50%, -50%); }
I can also recommend this tool: http://howtocenterincss.com/
Here's a solution using flexbox:
#wrapper {
display: flex; /* establish flex container */
flex-direction: column; /* stack flex items vertically */
position: relative; /* establish neares positioned ancenstor for absolute positioning */
}
h1 {
color: red;
}
.text {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
color: white;
font-weight: bold;
}
.center-aligned {
display: flex;
align-items: center;
justify-content: center;
}
<div id="wrapper" class="center-aligned">
<img class="background-image" src="http://michaelmossey.com/demo/home-hiker-grayish.jpg" />
<div class="text"><h1>Math Achivement Tutoring<h1></div>
</div>
Using a background image on a div and a display flex on the text might do it. Make sure to add the height on the text based on the image so it can be centered.
*{margin: 0 auto;}
.bg{
background-image:url('http://michaelmossey.com/demo/home-hiker-grayish.jpg');
height: 380px;
background-repeat: no-repeat;
background-size:cover;
background-position: center center;
}
.bg h1{
display: flex;
justify-content: center;
align-items: center;
height: 380px;
font-size: 3em;
color: #ffffff;
background-color: rgba(0,0,0,0.5);
}
<div class="bg">
<h1>Math Achivement Tutoring</h1>
</div>

Absolute positioning :after and transforming it not aligning it in center

Hey guys I had to create simple dots on a carousel like so:
And hence I used the following method:
.banner-nav-dots > li > a {
position: relative;
}
.banner-nav-dots > li.active > a:after {
content: '';
background: #6e2c91;
height: 5px;
width: 5px;
display: inline-block;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%);
-o-transform: translate(-50%,-50%);
transform: translate(-50%,-50%);
border-radius: 50%;
}
Now that should have really centered the dot , but as can be seen on THIS LINK, they are not exactly aligning in the center. Why? Why are they not aligning in the center?
Below is a MVCE:
.circle {
position: relative;
box-sizing: border-box;
display: inline-block;
border: 2px solid #6e2c91;
border-radius: 50%;
height: 15px;
width: 15px;
}
.circle:after {
position: absolute;
content: '';
display: inline-block;
height: 5px;
width: 5px;
top: 50%;
left: 50%;
border-radius: 50%;
background: #6e2c91;
transform: translate(-50%, -50%);
}
<div class='circle odd-numbered'></div>
I am more interested in the WHY part. Can somebody explain please?
P.S. this absolute position method combined with transform has always worked for me, but just on this instance its caused this issue and I don't know why. Checked both in FF and Chrome.
The problem seems to be due to a combination of odd numbered dimensions for parent container (height: 15px, width: 15px) and the 50% value for positioning attributes on child (top: 50%, left: 50%). This means that the actual calculated value will be 5.5px ((15px - 4px) / 2) for left and top (15px - 4px due to box-sizing: border-box also being applied on the parent).
When such fractional values are encountered, it looks like the browsers round-off the value. I couldn't find anything about this in the specs (whether it should be a round-up or down) and there aren't many recent articles on the net also about this particular thing. However, I did manage to find this old article which says that each browser treats them differently. Some round it down whereas others round it up. Either ways, the child element is not going to at the exact center.
The fix for this case seems to be to set an even-numbered value for the parent's dimensions.
.circle {
position: relative;
box-sizing: border-box;
display: inline-block;
border: 2px solid #6e2c91;
border-radius: 50%;
}
.odd-numbered {
height: 15px;
width: 15px;
}
.even-numbered {
height: 16px;
width: 16px;
}
.circle:after {
position: absolute;
content: '';
display: inline-block;
height: 5px;
width: 5px;
top: 50%;
left: 50%;
border-radius: 50%;
background: #6e2c91;
transform: translate(-50%, -50%);
}
<h4>Odd Numbered Dimensions - PROBLEM </h4>
<div class='circle odd-numbered'></div>
<h4>Even Numbered Dimensions - NO PROBLEM </h4>
<div class='circle even-numbered'></div>

How to set ribbon on image by stacking it in a div?

I currently have an ng-repeat that looks like this:
<div class="repeaterDiv" data-ng-repeat="item in itemArray">
<div class="wrapper">
<img class="imageClass" ng-src="{{item.image}}"/>
<div class="corner-ribbon bottom-right sticky green shadow">Changed</div>
</div>
</div>
Here is the CSS pulled from this codePen:
.corner-ribbon{
width: 200px;
background: #e43;
position: absolute;
top: 25px;
left: -50px;
text-align: center;
line-height: 50px;
letter-spacing: 1px;
color: #f0f0f0;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
}
.corner-ribbon.sticky{
position: fixed;
}
.corner-ribbon.shadow{
box-shadow: 0 0 3px rgba(0,0,0,.3);
}
.corner-ribbon.bottom-right{
top: auto;
right: -50px;
bottom: 25px;
left: auto;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
}
.corner-ribbon.green{background: #2c7;}
I am trying to figure out how to get the ribbon to be restricted to the wrapper class. Does anyone know how I can do that? so I'm still using the same ribbon, but instead of being in the bottom right of the screen, it is at the bottom right of the image for which it applies?
you need to use relative/absolute position and reset display of .wrapper to shrink on image. Then add overflow:hidden to cut off edges of ribbon:
.corner-ribbon {
width: 200px;
background: #e43;
position: absolute;
top: 25px;
left: -50px;
text-align: center;
line-height: 50px;
letter-spacing: 1px;
color: #f0f0f0;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
}
.corner-ribbon.sticky {
position: absolute;
}
.corner-ribbon.shadow {
box-shadow: 0 0 3px rgba(0, 0, 0, .3);
}
.corner-ribbon.bottom-right {
top: auto;
right: -50px;
bottom: 30px;
left: auto;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
}
.corner-ribbon.green {
background: #2c7;
}
.wrapper {
position: relative;
display: table-cell;/* or inline-block or float */
overflow: hidden;
}
img {
display: block;
}
<div class="repeaterDiv" data-ng-repeat="item in itemArray">
<div class="wrapper">
<img class="imageClass" ng-src="{{item.image}}" src="http://lorempixel.com/300/200" />
<div class="corner-ribbon bottom-right sticky green shadow">Changed</div>
</div>
</div>
The class has fixed positioning.
.corner-ribbon.sticky{
position: fixed;
}
So for exact css you may not be able to attach ribbon to each img, rather ribbon would go to specific place in window only. However, you can adjust css a bit. Make wrapper class relative, and .corner-ribbon.sticky absolute position. Then adjust your css fot top/bottom/left/right properties to align them.
.wrapper{
position: relative;
}
.wrapper .corner-ribbon.sticky{
position: absolute;
/* put top/bottom/left/right values here*/
}