How To Kern SVG text - css

I have some SVG text on a web page and I would like to kern a couple of the letters - how do I go about doing this? With HTML I would just wrap the letters in <span> tags and move them with the position property, but this doesn't work with SVG.
For instance, how would I move the letter 'o' in work in the code snippet provided?
Any help would be awesome.
body {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 100%;
height: 300vh;
margin: 0;
padding: 0;
font-family: arial-black;
}
text {
font-size: 2rem;
}
<svg class="git-svg" width="500" height="400" viewBox="0 0 500 400">
<text x="15" y="26" fill="#000">How We Work</text>
</svg>
codepen: https://codepen.io/emilychews/pen/PgmoOE

SVG has a tspan tag that you're supposed to use for precise positioning of text within a text element:
https://developer.mozilla.org/en-US/docs/Web/SVG/Element/tspan

You can only try property letter-spacing.
body {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 100%;
height: 300vh;
margin: 0;
padding: 0;
font-family: arial-black;
}
text {
font-size: 2rem;
letter-spacing: 2px;
}
<svg class="git-svg" width="500" height="400" viewBox="0 0 500 400">
<text x="15" y="26" fill="#000">How We Work</text>
</svg>

Related

Positioning issue with SVG element because of excess height space

I am trying to position the SVG elements in the middle of the buttons elements and make sure that the SVGs are taking up 100% of the width of the button. Everything I have tried either makes the SVG centered, but super small (Which I do not want), or positioned incorrectly. I want the actual icons to span the width of the button elements.
I should add that when inspecting element I am noticing that the svg elements have some weird access white space on the height so for reason whereas the path elements dont. I have no idea what this is for, but think it might be why it is so hard to style it.
.container {
width: 3rem;
border: 0.1rem solid black;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
gap: 0.25rem;
}
.container > button {
/*display: flex;
align-items: center;
justify-content: center;*/
width: 1rem;
height: 1rem;
background-color: #eee;
border: none;
cursor: pointer;
}
.container > button > svg {
width: 1rem;
}
<div class='container'>
<button type='button'>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Pro 6.2.1 by #fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M182.6 137.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-9.2 9.2-11.9 22.9-6.9 34.9s16.6 19.8 29.6 19.8H288c12.9 0 24.6-7.8 29.6-19.8s2.2-25.7-6.9-34.9l-128-128z"/></svg>
</button>
<button type='button'>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Pro 6.2.1 by #fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M137.4 374.6c12.5 12.5 32.8 12.5 45.3 0l128-128c9.2-9.2 11.9-22.9 6.9-34.9s-16.6-19.8-29.6-19.8L32 192c-12.9 0-24.6 7.8-29.6 19.8s-2.2 25.7 6.9 34.9l128 128z"/></svg>
</button>
</div>
Give the <svg> a width and height of 100% and add an attribute preserveAspectRatio="xMidYMid slice".
Since you were complaining the result was so small, I recommend setting box-sizing: content-box; so the (currently default) padding is added to the 1rem width.
.container {
width: 3rem;
border: 0.1rem solid black;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
gap: 0.25rem;
}
.container > button {
/*display: flex;
align-items: center;
justify-content: center;*/
width: 1rem;
height: 1rem;
box-sizing: content-box;
background-color: #eee;
border: none;
cursor: pointer;
}
.container > button > svg {
width: 100%;
height: 100%;
}
<div class='container'>
<button type='button'>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" preserveAspectRatio="xMidYMid slice"><!--! Font Awesome Pro 6.2.1 by #fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M182.6 137.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-9.2 9.2-11.9 22.9-6.9 34.9s16.6 19.8 29.6 19.8H288c12.9 0 24.6-7.8 29.6-19.8s2.2-25.7-6.9-34.9l-128-128z"/></svg>
</button>
<button type='button'>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" preserveAspectRatio="xMidYMid slice"><!--! Font Awesome Pro 6.2.1 by #fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M137.4 374.6c12.5 12.5 32.8 12.5 45.3 0l128-128c9.2-9.2 11.9-22.9 6.9-34.9s-16.6-19.8-29.6-19.8L32 192c-12.9 0-24.6 7.8-29.6 19.8s-2.2 25.7 6.9 34.9l128 128z"/></svg>
</button>
</div>
Because you are using svg from external library, fontawesome in this case, I suggest not to play with the viewbox. Better is to size the element around, svg will take it's place and size, path is relative to it's viewbox.
User agent will give by default some margin and padding, so for container button add margin 0 and padding 0, plus text-align center.
For button svg put it as inline-block so the sizing will effect. width and height you want, in this case, 1rem. And repeat margin 0 and padding 0 to avoid user agent effect.
.container {
width: 3rem;
border: 0.1rem solid black;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
gap: 0.25rem;
}
.container>button {
/*display: flex;
align-items: center;
justify-content: center;*/
width: 1rem;
height: 1rem;
background-color: #eee;
border: none;
cursor: pointer;
text-align: center;
margin: 0;
padding: 0;
}
.container>button>svg {
display: inline-block;
width: 1rem;
height: 1rem;
margin: 0;
padding: 0;
}
<div class='container'>
<button type='button'>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path
d="M182.6 137.4c-12.5-12.5-32.8-12.5-45.3 0l-128 128c-9.2 9.2-11.9 22.9-6.9 34.9s16.6 19.8 29.6 19.8H288c12.9 0 24.6-7.8 29.6-19.8s2.2-25.7-6.9-34.9l-128-128z"/></svg>
</button>
<button type='button'>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Pro 6.2.1 by #fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M137.4 374.6c12.5 12.5 32.8 12.5 45.3 0l128-128c9.2-9.2 11.9-22.9 6.9-34.9s-16.6-19.8-29.6-19.8L32 192c-12.9 0-24.6 7.8-29.6 19.8s-2.2 25.7 6.9 34.9l128 128z"/></svg>
</button>
</div>

Flexbox and SVG content

<body>
<div class="home">
<div class="title-header">
<div>HEADER</div>
</div>
<div class="main">
<div class="left-pane">
<div class="content">
<!-- SVG overflows the container on resize -->
<svg height="100%" width="100%" viewbox="0 0 200 200" preserveAspectRatio="xMidYMin meet">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
<!-- Using a Div instead works great!
<div style="width: 100%; height: 100%; background-color: white">
</div> -->
</div>
</div>
<div id="rightpane" class="right-pane">
<button onClick="toggleSize()">Resize</button>
</div>
</div>
</div>
<div class="footer">
<div>FOOTER</div>
</div>
</body>
</html>
.home {
display: flex;
flex-direction: column;
width: 1000px;
height: 800px;
background-color: lightgray;
}
.title-header {
width: 100%;
display: flex;
flex: 0 0 35px;
height: 35px;
background-color: lightblue;
align-items: center;
justify-content: center;
}
.main {
display: flex;
width: 100%;
flex: 1;
background-color: lightgreen;
}
.left-pane {
display: flex;
flex: 1;
flex-direction: column;
background-color: white;
}
.right-pane {
flex: 0 0 350px;
width: 350px;
border-left: 1px solid lightgray;
&.min {
flex: 0 0 100px;
width: 100px;
}
}
.content {
width: 100%;
height: 100%;
background-color: yellow;
}
.footer {
display: flex;
position: absolute;
top: 810px;
left: 0px;
flex: 0 0 35px;
width: 1000px;
height: 35px;
border: 1px solid black;
align-items: center;
justify-items: center;
}
Example is here: https://codepen.io/johnny4111/pen/ZEYNqyq
I have a structure as in the example, it's a container that has a left and right pane. The right pane can be minimized programmatically. The Left pane has an SVG set to take up 100% height and 100% width. The left pane has flex-grow set to 1 so that it takes up 100% of the free height but should not exceed the bounds of it's parent div.
The expectation is when the right pane is minimized and the left pane expands it's width to take up the now available free space the SVG should still constrain itself to the available height (100% height) since the height has not changed, just the width. However, in reality it overflows the div. There is a absolute positioned footer at the bottom so you can see it overflows into that.
Any ideas what the problem is? If I use a regular div set to 100% width, 100% height instead of an SVG it works without any issues. The Div does not overflow it's parent.

strange behavior / problems with the positioning of a text in an SVG // IE problems

I'm just about to position a text (a headline) in a SVG vertically AND, that the IE also kept the peculiar width. BUT in IE, this headline is made smaller and somehow funny. Well, now I've read about a paddin-bottom-hack that I've used now. Here is my source code:
h1 {
display: flex;
flex: 0 0 3em;
min-height: 5em;
flex-direction: column;
justify-content: center;
align-content:center;
font-family: 'Variable-Bold';
font-size: 1.6em;
line-height: 1;
letter-spacing:0;
margin-right: 0.6em;
max-width: 3.5em;
border: 6px dotted yellow;
}
.scaling-svg-container {
position: relative;
width: 100%;
padding: 0;
padding-bottom: 100%;
}
h1 svg {
display: inline-block;
height: 100%;
max-height: 13em;
position: absolute;
height: 100%;
width: 100%;
left: 0;
top: 0;
}
<h1 class="scaling-svg-container"
style="padding-bottom: 24.0385%">
<svg viewBox="0 0 50 208" preserveAspectRatio="xMidYMid meet"
xmlns="http://www.w3.org/2000/svg">
<path id="verticalPath" fill="none" stroke="none" d="M37.05,208 V0"/>
<rect x=4 y=4 width=42 height=200 stroke-width="3" stroke="#ff6e00" fill="none"/>
<text x="104.3" text-anchor="middle" fill="#ff6e00">
<textpath href="#verticalPath">Meine Überschrift</textpath>
</text>
</svg>
</h1>
In IE it currently looks like this:
SCREEN IE
The headline is displayed within the area with (orange) border from the middle (indicated here with a yellow line) towards the top! WHY DO THIS BELOW? Why is not the headline displayed from bottom to top? What is wrong here in the source code? And that is only in IE!
Second PROB)
In all other browsers, the orange-bordered headline is now no longer displayed (vertical) centered (in the up-front yellow, dotted area), the display flex; and flex-direction: column; justify-content: center; align-content: center; , all that does not work now, suppose that has the position: relative; / position: absolute; to do. With which option can I now in (two) directions (what just get content-content: center; align-content: center; get) this heading (center) position? How do you do that?
Oh yes: An example can be seen here Visual link website
Can you help me please?
The misanthrop

Align <video> center of flexbox with variable height

I have a video page with 3 primary elements (header, video, settings footer). The settings footer is collapsable.
I am happy with the layout when the settings footer is visible, but I wish I could increase the size of the video to take up the remaining height once the settings footer is collapsed. In other words, the video should grow in size slightly on footer collapse.
Here is what I have so far:
var el = document.getElementsByClassName("settings-container")[0];
el.addEventListener("click", function(e) {
e.target.classList.toggle("collapsed");
});
body {
font-size: 16px;
}
.main-container {
display: flex;
flex-direction: column;
min-height: 100vh;
overflow: hidden;
}
.header-container {
align-items: center;
border-bottom: 0.0625rem solid #b2b2b2;
display: flex;
flex: 0 0 1.938rem;
padding: .25rem .9375rem;
}
.video-container {
align-items: center;
display: flex;
flex: 1 1 auto;
justify-content: center;
padding: .9375rem;
}
.video-container .video-player {
border: 0.1875rem solid black;
display: flex;
overflow: hidden;
position: relative;
}
my-video-player {
background-color: transparent;
display: block;
font-family: arial, sans-serif;
font-size: 12px;
position: relative;
}
my-video-player .video video {
height: auto;
max-height: calc(100vh - 19.75rem);
max-width: 100%;
width: auto;
}
.settings-container {
background: #f4f4f4;
display: flex;
flex: 0 1 15rem;
flex-direction: column;
position: relative;
top: 0;
transition: flex .5s;
}
.settings-container.collapsed {
flex: 0 0 2.4rem;
}
<div class="main-container">
<div class="header-container">Header</div>
<div class="video-container">
<div class="video-player">
<my-video-player>
<div class="video">
<video autobuffer controls>
<source id="mp4" src="http://footage.framepool.com/mov/521-436-838.mp4" type="video/mp4">
</video>
</div>
</my-video-player>
</div>
</div>
<div class="settings-container">Settings - click me to collapse</div>
</div>
Best viewed in fullscreen!
I am looking for a css-only solution where the video takes up the available space between the header and the footer. Right now I have hard-coded a max-height to the video element to make it fit, but my attempts to solve this otherwise have failed.
I have already seen posts suggesting position: absolute and relative to the child and parent respectively, but the many levels of flexbox is making this hard for me.
Thankful for any ideas or suggestions.

Aligning SVGs using flex

I'm using flex to layout a menu for a website and I'm having a heck of a time trying to align an SVG to the right. I'm not sure what I'm doing wrong because I'm using SVGs inside of flexboxes for my social icons and they're lining up proplerly.
Here is my code for the css and the structure:
.seventh {
display: flex;
width: 100%;
height: calc(100% / 7);
overflow: hidden;
margin: auto;
}
div.link,
div.blank {
display: flex;
justify-content: flex-end;
width: 46.25%;
height: 100%;
position: relative;
flex-flow: column nowrap;
overflow: hidden;
margin-right: 0;
}
.svgLink.left {
display: block;
margin-right: 0;
height: 100%;
}
<section id="blue" class="seventh">
<div class="link">
<svg class="svgLink left" viewBox="0 0 431.1 73.1">
<text transform="matrix(1 0 0 1 -0.2852 63.7813)" font-family="'Panton_xbk'" font-size="74.5982px">MARKETING</text>
</svg>
</div>
<div class="pixel">
<svg class="pixel" viewBox="0 0 512 512">
<circle cx="256" cy="256" r="250" class="vf6"></circle>
</svg>
</div>
<div class="blank"></div>
</section>
This is what I am trying to get it to look like:
There are a few things you should watch out when using flexbox.
If you are trying to align the SVG's to the right the most important thing would be to remove the the last div with class="blank". In general it is actually a bad practice to use empty div's for styling as you can do it with css (especially if you are using flexbox).
If you want to style specific child elements use the appropriate css properties.
There is a really great guide on how to use flexbox layout.
But let's continue with your code example:
I have stripped out unnecessary code from your snippet and modified the css to use the flexbox layout. If you want to align the SVG's to the left use justify-content: flex-start; and if they should be aligned to the right use justify-content: flex-end; in the class selector .seventh as provided in the example below.
.seventh {
display: flex;
flex-flow: row nowrap;
justify-content: flex-end;
align-items: center;
width: 100%;
overflow: hidden;
margin: auto;
}
div.link {
width: 46.25%;
}
div.pixel {
width: 7.5%;
}
div.pixel>svg {
height: 100%;
}
<section id="blue" class="seventh">
<div class="link">
<svg class="svgLink left" viewBox="0 0 451.1 73.1">
<text transform="matrix(1 0 0 1 -0.2852 63.7813)" font-family="'Panton_xbk'" font-size="74.5982px">MARKETING</text>
</svg>
</div>
<div class="pixel">
<svg viewBox="0 0 512 512">
<circle cx="256" cy="256" r="250" class="vf6"></circle>
</svg>
</div>
</section>

Resources