Vertical Align Text Inside Container even when font size changes - javascript

I'm trying to vertical-align: middle a text inside a container with different font sizes. This has been asked before, but I can't get any of the solutions to work for me, What I'm missing?
I want the text with different font sizes to align vertically in the middle of the container.
Here is the code:
.
let upperGuideText = document.getElementById("upperGuideText");
let guide = "Some text here"
setTimeout(function(){
upperGuideText.style.fontSize = "3vw";
upperGuideText.innerHTML = `${guide}`;
}, 500);
setTimeout(function(){
upperGuideText.style.fontSize = "5vw";
upperGuideText.innerHTML = `${guide}`;
}, 2500);
.upperGuideContainer {
position: absolute;
overflow: hidden;
left: 10vw;
top: 51vh;
height: 26vh;
width: 88vw;
display: flex;
justify-content: center;
align-items: center;
outline: 0.1vw dashed orange;
}
.upperGuide {
position: absolute;
font-family: 'Open Sans', sans-serif;
font-weight: bold;
color: rgb(128, 128, 128);
left: 0.5vw;
top: -11.4vh;
opacity: 1;
vertical-align: middle;
}
<div class = "upperGuideContainer">
<p id="upperGuideText" class="upperGuide"></p>
</div>

You're asking your CSS to do two different things, which is causing your problem.
the below flexbox properties that you included in the parent container are enough to achieve what you want.
.upperGuideContainer {
display: flex;
justify-content: center;
align-items: center;
}
When you tell the child <p> to take an absolute position, you're breaking the flexbox properties of the parent
.upperGuide {
/* position: absolute; */
font-family: 'Open Sans', sans-serif;
font-weight: bold;
color: rgb(128, 128, 128);
/* left: 0.5vw; */
/* top: -11.4vh; */
opacity: 1;
/* vertical-align: middle; */
}
EDIT: If you want to learn more about the magical properties of flexbox, I highly recommend this article. I reference it constantly.

I think you are using position absolute on the child when you don't really need to do it. once your parent container has "display: flex" as a property you can align things with "align-items" and "justify-content", there is no need for the child to have position absolute unless you need it to for other purposes.
.upperGuideContainer {
position: absolute;
overflow: hidden;
left: 10vw;
top: 51vh;
height: 26vh;
width: 88vw;
display: flex;
justify-content: center;
align-items: center;
outline: 0.1vw dashed orange;
}
.upperGuide {
/*position: absolute;*/
font-family: 'Open Sans', sans-serif;
font-weight: bold;
color: rgb(128, 128, 128);
/*left: 0.5vw;*/
/*top: -11.4vh;*/
opacity: 1;
/*vertical-align: middle;*/
}
As a side note, if you are using position absolute in a container inside of an absolute container, you should avoid using vh (viewport height) and vw (viewport width) as these are values coming from the viewport. I recommend using % or px instead as these are more accurate.

Remove position:absolute, and top from .upperGrid. Because when you use absolute it is positioned according to the nearest containing block that is not absolute. Also the element is taken out of the flex display.
.upperGuideContainer {
position: absolute;
overflow: hidden;
left: 10vw;
top: 51vh;
height: 26vh;
width: 88vw;
display: flex;
justify-content: center;
align-items: center;
outline: 0.1vw dashed orange;
}
.upperGuide {
font-family: 'Open Sans', sans-serif;
font-weight: bold;
color: rgb(128, 128, 128);
left: 0.5vw;
opacity: 1;
vertical-align: middle;
}

Related

Baseline alignment of absolute child

I'm trying to build a Unicode table which can compare glyph blackspace between fonts.
My intention is for user-selected fonts on the table; Obviously, fonts have different (unknown) metrics. So—as per the following example—is it possible to align the children's font to the parents' font's baseline after absolutely positioning the child glyph objects?
#box{
display: flex;
justify-content: center;
align-items: center;
font-size: 72pt;
/* dimension ref */
border: 1px solid blue;
}
#box > span {
display: inline-flex;
justify-content: center;
font-family: serif;
border: 1px solid #F0F;
}
#box > span > span {
position: absolute;
mix-blend-mode: difference;
font-family: cursive;
color: red;
/* alignment ref */
outline: 1px solid #0F0;
}
<div id="box">
<span>x<span>x</span></span>
<span>y<span>y</span></span>
<span>z<span>z</span></span>
<span>!<span>!</span></span>
</div>
My preferred solution would be pure CSS, but a scan of the available resources indicates that's unlikely. Are font metrics exposed at all to JavaScript, such that I could just calculate a top or bottom margin and shove it in as a CSS variable?
Otherwise, I'm left pulling relative child glyph objects left (read as: towards flex "start") by half their width plus half the parent width? And that gets messy because I'll need per-character adjustments and that's a time-consuming calculation when I'm displaying 10K+ glyphs and the user changes fonts…
EDIT: As reference, my system uses "Georgia" as serif and "Comic Sans MS" as cursive. I also am testing initial resulting in Gecko/Firefox, then aligning them to Chromium. Normally this might not matter, but these are areas where different browsers/engines may render with subtle differences. For the above fonts, default baselines in Word align as follows:
"Comic Sans" 'z' and '!' should bleed under the baseline, as does right side of the 'x'.
'y' actually connects above the baseline
All glyphs both ascend higher and descend lower than their respective "Georgia" glyph.
Maybe you can do something like this. I've wrapped each "letter" into their own div. Then set both the first span and the child span to position: absolute; and set both of them to bottom: 0; giving them the same baseline.
I also gave the new dives a margin in order to space the letters out a bit. Check out what I did here:
#box{
display: inline-block;
justify-content: center;
align-items: center;
font-size: 72pt;
/* dimension ref */
border: 1px solid blue;
}
#box > div {
position: relative;
height: 100px;
display: inline-block;
margin: 30px;
}
#box > div > span {
display: inline-flex;
justify-content: center;
font-family: serif;
border: 1px solid #F0F;
position: absolute;
bottom: 0;
}
#box > div > span > span {
position: absolute;
mix-blend-mode: difference;
font-family: cursive;
color: red;
/* alignment ref */
outline: 1px solid #0F0;
bottom:0;
}
<div id="box">
<div><span>x<span>x</span></span></div>
<div><span>y<span>y</span></span></div>
<div><span>z<span>z</span></span></div>
<div><span>!<span>!</span></span></div>
</div>
Well, I may have lost the forest for the trees: letter-spacing at -1em for the parent glyph seems to avoid the need for absolute positioning of the child glyph while maintaining the original inline baseline. Flex is also unneeded for the glyph parent.
Additional benefit is that the outlines now conform to the individual font dimensions rather than being homogenized by flex and absolute positioning.
(Of note: mix-blend-mode is imperative to what I'm trying to accomplish, but doesn't seem to be honored by the snippet console for text, only the box model. So, use your imagination or demo elsewhere. Highlighting the text in the snippet result also demos the intended effect.)
div#box {
font-size: 72pt;
letter-spacing: -1em;
/* box ref */
outline: 1px solid #F0F;
}
#box > span {
font-family: serif;
/* dim ref */
outline: 1px solid #000;
}
span > span {
mix-blend-mode: difference;
font-family: cursive;
color: #0FF;
letter-spacing: 0em;
/* dim ref */
outline: 1px solid #0FF;
}
<div id="box">
<span>x<span>x</span></span>
<span>y<span>y</span></span>
<span>z<span>z</span></span>
<span>!<span>!</span></span>
</div>
A rare example of em doing what I would expect rather than something bizarre.
Set box position to relative then control absolute children's position with px or %
#box{
display: flex;
justify-content: center;
align-items: center;
font-size: 72pt;
/* dimension ref */
border: 1px solid blue;
position: relative;
}
#box > span {
display: inline-flex;
justify-content: center;
font-family: serif;
border: 1px solid #F0F;
}
#box > span > span {
position: absolute;
mix-blend-mode: difference;
font-family: cursive;
color: red;
/* alignment ref */
outline: 1px solid #0F0;
bottom: 1%;
}
<div id="box">
<span>x<span>x</span></span>
<span>y<span>y</span></span>
<span>z<span>z</span></span>
<span>!<span>!</span></span>
</div>
put them on the side
#box{
display: flex;
justify-content: center;
align-items: center;
font-size: 72pt;
/* dimension ref */
border: 1px solid blue;
position: relative;
}
#box > span {
display: inline-flex;
justify-content: center;
font-family: serif;
border: 1px solid #F0F;
position: relative;
width: 70px;
margin-right: 50px;
}
#box > span > span {
position: absolute;
mix-blend-mode: difference;
font-family: cursive;
color: red;
/* alignment ref */
outline: 1px solid #0F0;
bottom: -1%;
left: 70px;
width: 50px;
}
<div id="box">
<span>x<span>x</span></span>
<span>y<span>y</span></span>
<span>z<span>z</span></span>
<span>!<span>!</span></span>
</div>
EDIT: regarding your comment:
for that, I think it will be better to put letters in one container, then position both of them absolute with baseline alignment. the following example shows that without any additional positioning, meaning it's the baseline of the font. and you can adjust positioning using bottom
#box{
display: flex;
justify-content: center;
align-items: baseline;
font-size: 72pt;
/* dimension ref */
border: 1px solid blue;
position: relative;
height: fit-content;
padding: 100px;
}
.black {
position: absolute;
display: flex;
text-decoration: underline;
justify-content: center;
font-family: serif;
border: 1px solid #F0F;
letter-spacing: 30px;
}
.red {
display: flex;
text-decoration: underline;
position: absolute;
mix-blend-mode: difference;
font-family: cursive;
color: red;
border: 1px solid lightgreen;
letter-spacing: 30px;
}
<div id="box">
<div class="black">XYZ!</div>
<div class="red">XYZ!</div>
</div>

Unwanted gap on absolute positioned content on top of relative positioned content

I'm playing around with Chris Coyiers brilliant approach to full page video with content scrolling over the video, but I'm getting an unwanted gap to the right in Windows browsers. The weird thing is that it's not happening in Mac browsers (currently testing in Safari, Firefox and Chrome). In Windows browsers this happens in all the browsers I'm testing with.
The css for the white main content area looks like this:
main {
background: white;
position: relative;
padding: 1rem;
margin-top: 100vh;
}
main::before {
content: "";
width: 100vw;
height: 100vh;
position: absolute;
left: 0;
top: -100vh;
}
Could it be scrollbar related? Has anyone found a solution to this or can explain to me why this happens in Windows?
Please see this Fiddle: https://jsfiddle.net/8y2v79nj/
Chris' article: https://css-tricks.com/full-page-background-video-styles/
Chris' example that I'm using: https://codepen.io/chriscoyier/pen/BRvdgK
Mac screenshot with no gap:
Windows screenshot with the unwanted gap:
The problem is from the reserved width for the y-scroller, and you only hide the x-scroller by overflow-x: hidden; on body.
You can add this to your styles that will help you to get rid of the reserved width of the scroller on body.
body::-webkit-scrollbar {
display: none;
}
Full code
var viewportHeader = document.querySelector(".viewport-header");
document.body.addEventListener("scroll", function(event) {
var opacity = (document.body.offsetHeight - document.body.scrollTop) / document.body.offsetHeight;
var scale = (document.body.offsetHeight - document.body.scrollTop) / document.body.offsetHeight;
document.documentElement.style.setProperty('--headerOpacity', opacity);
document.documentElement.style.setProperty('--headerScale', scale);
});
:root {
--headerOpacity: 1;
--headerScale: 1;
}
.video-header {
position: absolute;
text-align: center;
width: 100vw;
height: 100vh;
}
.video-header,
.video-header video,
.video-header .viewport-header {
width: 100vw;
height: 100vh;
position: absolute;
top: 0;
left: 0;
}
.video-header video {
background: brown;
object-fit: cover;
}
.video-header .viewport-header {
display: flex;
align-items: center;
justify-content: center;
opacity: 1;
opacity: var(--headerOpacity);
transform: scale(var(--headerScale));
}
html,
body {
height: 100vh;
overflow-x: hidden;
}
body::-webkit-scrollbar {
display: none;
}
html {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 150%;
line-height: 1.4;
}
body {
margin: 0;
}
h1 {
font-family: "Syncopate", sans-serif;
color: white;
text-transform: uppercase;
letter-spacing: 3vw;
line-height: 1.2;
font-size: 3vw;
text-align: center;
}
h1 span {
display: block;
font-size: 10vw;
letter-spacing: -1.3vw;
}
main {
background: white;
position: relative;
padding: 1rem;
margin-top: 100vh;
}
main::before {
content: "";
width: 100vw;
height: 100vh;
position: absolute;
left: 0;
top: -100vh;
}
main p {
max-width: 600px;
margin: 1rem auto;
}
<header class="video-header">
<video src="https://css-tricks-post-videos.s3.us-east-1.amazonaws.com/Island%20-%204141.mp4" autoplay loop playsinline muted></video>
<div class="viewport-header">
<h1>
Explore
<span>Montana</span>
</h1>
</div>
</header>
<main>
<p>
test
</p>
<p>
test
</p>
<p>
test
</p>
<p>
test
</p>
<p>
test
</p>
<p>
test
</p>
</main>

Circular progress bar position

There is a circular progress bar. This bar prints the number of days remaining, taking the day difference. But I'm having trouble adjusting the position of this bar.
I am trying to do;
What I've been able to do so far;
html
<div className={'circularremainingtime__container only-desktop' + circularColor}>
<div className="remainingday">
<p>{endDate.getDate()}</p>
<p>{endDateMonth}</p>
</div>
<AS.CircularProgress
className="circularprogress"
style={style}
variant="determinate"
value={persentage}
thickness={3}
/>
<p>{circularText}</p>
</div>
css
.circularremainingtime__container.only-desktop {
width: 110px;
display: flex;
flex-direction: column;
align-items: center;
padding-left: 1.5em;
& > p {
margin: 0;
font-weight: 600;
margin-top: 0.5em;
font-size: 1.2rem;
font-weight: 500;
color: var(--palette-red-300);
}
& > div {
padding: var(--padding);
}
.circularprogress {
color: var(--palette-red-300);
}
.remainingday {
//position: absolute;
color: #004dcf !important;
padding-top: 5px;
p{
margin: 0;
text-align: center;
color: #004dcf !important;
font-size: 8px;
font-weight: bolder;
}
p:first-child{
font-size: 13px;
text-align: center;
}
}
}
When I set the remainingday class to absolute, I can get the image I want. But when I swipe the screen, the dates don't change at all. That's why I commented that line.
You need to use position: absolute; top:0px; for . circularprogress in your style because what you are doing is rendering the element next to the div, that's why it is showing below that.
Cheers.

Background image increase size with scroll

I am trying to make the background image on a div change its scale as per the amount of page scrolled. Works well on desktop screens but on mobile screen, the BG image's height reduces and shrinks the image. This behaviour is apparent as I am trying to resize a sized cover image in % values. I have added a red background-color too to the div for better debugging. Any way to make it work flawlessly even on mob screens? The code is below as well as on Codepen.
HTML:
<main>
<div class="section_1">
<div class="welcome_message">
<div class="welcome_text">
<p class="welcome">Welcome to</p>
<h1>My</h1>
<p class="tagline">DIRECTORY</p>
</div>
</div>
</div>
</main>
CSS:
main{
min-height: 200vh;
}
.section_1{
position: relative;
width: 100%;
height: 90vh;
background: red url(https://images.pexels.com/photos/9467294/pexels-photo-9467294.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260) 40% 10%/cover no-repeat;
display: flex;
justify-content: flex-end;
align-items: flex-end;
}
.section_1 .welcome_message{
width: 80%;
min-height: 100%;
display: flex;
justify-content: flex-end;
align-items: flex-end;
background: none;
padding: 0 1rem 10rem 0;
.welcome_text{
z-index: 3;
// color: white;
background-color: rgba(1, 55, 131, 0.5);
border-bottom: 0.5rem solid white;
padding: 1rem 2rem;
border-end-start-radius: 2rem;
}
.welcome{
color: white;
font-weight: 400;
}
h1{
font-size: 2rem;
color: white;
font-weight: 600;
margin-block: -0.3em;
}
.tagline{
color: white;
font-weight: 400;
}
}
JS:
let bg = document.querySelector('body .section_1')
document.addEventListener('scroll', () => {
let x = window.pageYOffset
bg.style.backgroundSize = (100 + x/10)+'% auto'
})
you almost made it instead of using auto use the calculated width and set the height to 100%
bg.style.backgroundSize = ''+(130 + x/10)+'% 100%'
Codepen :)
Because you scroll all the way top again, bg.style.backgroundSize = 'auto 130%', The value of bg.style.backgroundSize should null.

Centering text vertically as it grows, in child class

I have a parent container(like a pop-up), in which I have a child element appended to parent container. The child element is a div which has some text. I want to center the text inside the div, so that the text remains center aligned in the child div, but the text should align itself vertically as it grows beyond 3-4 lines. I am able to align text vertically as it grows, but when it still is a small text it should be center vertically, which is not happening. I have tried lot of css properties in the child class.
Any help will be good.
.parentclass {
position: absolute;
top: 110px;
left: 165px;
width: 470px;
height: 260px;
text-align: center;
background-image: url(../images/Notification_BG.png); }
.childclass {
position: relative;
position: inherit;
width: 430px;
height: 192px;
left: 50%;
top: 50%;
margin-left: -215px;
margin-top: -96px; /* Negative half of height. */
text-align: center;
text-overflow: -o-ellipsis-lastline;
border: 1px solid blue;
font-family: Arial;
font-size: 28px;
color: white; }
Thanks
KK
have u used vertical-align:middle; ?
try this :
.childclass {
display: table-cell;
vertical-align: middle;
text-align: center;
}
This link will definitely help you:
vertically-center-text-in-a-100-height-div
Use your parentclass display as table and the childclass display as a table-cell and vertical-align:middle will work surely
html
<div class='parentclass'>
<div class='childclass'>Text which is more than two or three lines</div>
</div>
Css
.parentclass {
height: 260px;
text-align: center;
display:table;
}
.childclass {
vertical-align: middle;
width: 430px;
top: 50%;
text-align: center;
text-overflow: -o-ellipsis-lastline;
border: 1px solid blue;
font-family: Arial;
font-size: 28px;
color: black;
}
See this fiddle for demo

Categories

Resources