Baseline alignment of absolute child - javascript

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>

Related

How to arrange text to start from the bottom of div?

I would like to have text inside the element to be aligned such that it begins from the bottom of the page. I want it so that as I increase or decrease the width of the div, the text fills up the bottom first before the top.
I want to look like the following design from adobe illustrator:
Instead, it looks like the following:
the code used in the second image is below:
<style media="screen">
*{
font-family: 'Heebo', sans-serif;
}
.big-intro-text{
font-size: 100px;
width: 100%;
position: absolute;
}
.big-intro-text div{
border: solid 1px green;
text-align: left;
color: gray;
max-width: 800px;
height: auto;
display: inline-block;
vertical-align: text-bottom;
}
</style>
<div class="big-intro-text" align = "center">
<div>home of the zebras</div>
</div>
* {
font-family: 'Heebo', sans-serif;
}
.big-intro-text {
font-size: 100px;
width: 100%;
position: absolute;
}
span {
display: block;
}
.big-intro-text div {
border: solid 1px green;
text-align: left;
color: gray;
max-width: 800px;
height: auto;
display: inline-block;
vertical-align: text-bottom;
}
<div class="big-intro-text" align="center">
<div><span>home<span> of the zebras</div>
</div>
Try this code.
You could add a large amount of margin on the top, and reduce the div height.
Sorry about the old answer, I did not understand the question.

Vertical Align Text Inside Container even when font size changes

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;
}

CSS change size of text box with screen

I was creating a page on Reactjs. I have two react components, which are basically simple divs. Lets call one LeftPanel and the other one Right Panel.
So for left panel i have float set to left and for the right panel, i have float set to right, so that these panels appear on the respective sides of screen. (see screenshot attached).
The area left in the center, containing textbox and button is a div with following attributes:
.Area{
display: flex;
min-height: 125px;
align-content: center;
background-color: lightblue;
}
textarea and button have the following CSS:
.text{
display: flex;
width: 55em;
margin:3% 0% 0% 10%;
height: 33%;
font-size: x-large;
vertical-align: top;
resize:none;
border-top-left-radius:30em;
border-bottom-left-radius:30em;
border-color:black;
text-align: center;
outline: none;
box-shadow: 0px 5px 0px 0px rgb(51, 46, 46);
}
.searchBtn{
width:20em;
height: 38%;
margin-top:3%;
margin-right:10%;
border-top-right-radius: 30em;
border-bottom-right-radius:30em;
border-color:black;
outline:none;
box-shadow: 0px 4px 0px 0px rgb(51, 46, 46);;
}
Now, my problem is, that when i reduce the screen size, this happens:
Below 800px:
How do i fix this?
I can provide any further information if necessary.
You should avoid combining flex with float, because output behavior is often unexpectable. In below example I used flex for parent .container and for all children. I assume you want .leftPanel and .rightPanel to have defined min-width, so I added min-width: 250px; for .leftPanel (you can also add it to .rightPanel). Property flex: 1 for all children make them grow so to fit evenly .container, but all defined min-width are respected.
.container {
display: flex;
width: 100%;
}
.leftPanel, .rightPanel, .Area {
display: flex;
flex: 1;
border: 1px solid black;
}
.Area{
display: flex;
min-height: 125px;
align-content: center;
background-color: lightblue;
}
.leftPanel {
min-width: 250px;
}
<div class="container">
<div class="leftPanel">
leftPanel
</div>
<div class="Area">
Area
</div>
<div class="rightPanel">
rightPanel
</div>
</div>

jQuery width, outerWidth, innerWidth - return fake values

I want to absolutely position my buckles for animation and this is my html:
<div id="about">
<div id="weare">lorem.ipsum</div>
<div id="who"><span id="whospan"><B>LOREMSIT.DOLOR</B></span></div>
<div id="what"><div id="klamra_l">[</div><div id="klamra_r">]</div><span id="whatspan">Lorem ipsum dolor sit amet, consectetur.</span></div>
</div>
I am using for it jQuery:
function ustawklamry()
{
var w_what = parseInt($("#what").outerWidth(true));
var w_whatspan = parseInt($("#whatspan").outerWidth(true));
var left = parseInt((w_what - w_whatspan)/2);
var right = parseInt(left + w_whatspan);
$("#klamra_l").css("left",left);
$("#klamra_r").css("left",right);
console.log(w_what + ";" + w_whatspan + ";" + left + ";" + right);
}
ustawklamry();
And what I get is:
And in console I see:
964;596;184;780
What is more, the space between buckles is equal to #whatspan (green field).
I have no idea why it is not working. I tried width, outerWidth, innerWidth and no one is working.
Please for help, if you want any additional data - ask.
First, I will address your following problem.
Oh my god, I see it is working good on fiddle but on my website not... I thought about problem while page is loading and I used $(document).ready(function(){... but it is not working too. Where is the problem?
This is because code from other parts of the page are be interfering with your code for this part of the page. If you can't find it anywhere in your javascript, then it must be in your CSS. Try opening up the dev tools (inspecting the page) and see what CSS values that menu is inheriting from its parent element in your production page. Then, try inspecting the JSfiddle page. Finally, try to get the CSS inherited from the parent element on the production page to be the same as the CSS inherited from the parent element on the JSFiddle page. Now it should work. Also, pay very close attention to !important tags. I have a sneaking suspicion that they might be the culprit.
To the next issue: you don't actually need javascript. Also, your layout is inflexible, it will look good on some devices, and bad on others because you don't make the size adaptive to the user's screen size. Here is a demo that works in IE9 and automatically resizes based on the user's screen size by using vw units in the font size, and transform: translateY(.125em) to center the brackets. Also, you could cut down on your DOM usage. Considering all these things, I hope you find this very useful:
#about {
border: 2vw solid #FFF;
padding: 3vw;
//border-radius: 50% / 50%;
display: inline-block;
background-color: black;
max-width: 80vw;
outline: 99vh solid black;
box-shadow: 0 0 0 99vw black;
overflow: hidden;
position: fixed;
top:0;bottom:0;
left:5vw;right:5vw;
margin: auto 0;
height: 17.5vw;
}
#weare {
color: #FFF;
font-size: 3vw;
margin: 0 auto;
text-align: center
}
#who {
color: #FFF;
font-size: 9vw;
margin: 0 auto;
font-family: Oswald, sans-serif;
text-align: center;
letter-spacing: 133%;
font-weight: bold;
}
#what {
color: #FFF;
font-size: 2.5vw;
margin: 0 auto;
font-weight: 300;
text-align: center;
vertical-align: middle;
background-color: red;
}
#greenbackground::before {
direction: rtl;
}
#greenbackground::after, #greenbackground::before {
content: ']';
font-size: 2em;
transform: translateY(.125em);
background: none;
line-height: 0;
display:inline-block;
color: white;
width: 0;
}
#greenbackground {
background:green;
display:inline-block;
height: 100%;
}
<div id="about">
<div id="weare">lorem.ipsum</div>
<div id="who">LOREMSIT.DOLOR</div>
<div id="what"><span id="greenbackground">Lorem ipsum dolor sit amet, consectetur.</span></div>
</div>
JSFiddle Link
To add some snazzy roundness to it, all you need is 1 extra line of code.
#about {
border: 2vw solid #FFF;
padding: 3vw;
border-radius: 50% / 50%;
display: inline-block;
background-color: black;
max-width: 80vw;
outline: 99vh solid black;
box-shadow: 0 0 0 99vw black;
overflow: hidden;
position: fixed;
top:0;bottom:0;
left:5vw;right:5vw;
margin: auto 0;
height: 17.5vw;
}
#weare {
color: #FFF;
font-size: 3vw;
margin: 0 auto;
text-align: center
}
#who {
color: #FFF;
font-size: 9vw;
margin: 0 auto;
font-family: Oswald, sans-serif;
text-align: center;
letter-spacing: 133%;
font-weight: bold;
}
#what {
color: #FFF;
font-size: 2.5vw;
margin: 0 auto;
font-weight: 300;
text-align: center;
vertical-align: middle;
background-color: red;
}
#greenbackground::before {
direction: rtl;
}
#greenbackground::after, #greenbackground::before {
content: ']';
font-size: 2em;
transform: translateY(.125em);
background: none;
line-height: 0;
display:inline-block;
color: white;
width: 0;
}
#greenbackground {
background:green;
display:inline-block;
height: 100%;
}
<div id="about">
<div id="weare">lorem.ipsum</div>
<div id="who">LOREMSIT.DOLOR</div>
<div id="what"><span id="greenbackground">Lorem ipsum dolor sit amet, consectetur.</span></div>
</div>
JSFiddle Link

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