How would I use inline HTML elements in SVG? - html

I am wondering if there were a way to use inline HTML like <sup> and <sub> elements in SVG?
For example:
<svg>
<text x="0" y="12">Some text with a superscript <sup>1</sup> and a subscript <sub>2</sub>.</text>
</svg>
I can not find anything about using inline HTML elements in SVG. I am hoping to use superscript without having to use a styled <tspan>.

A possible solution to your problem is using tspan elements and the attribute baseline-shift like so:
tspan[baseline-shift]{font-size:50%;}
<svg viewBox="0 0 350 40">
<text x="0" y="12">Some text with a superscript <tspan baseline-shift="super">1</tspan> and a subscript <tspan baseline-shift="sub">2</tspan>.</text>
</svg>

I can not find anything about using inline HTML elements in SVG. I am
hoping to use superscript without having to use a styled <tspan>.
You can use for these purposes: foreignObject
<svg xmlns="http://www.w3.org/2000/svg" width="450" height="100">
<style type='text/css'>
svg { border: 1px solid black; }
svg div {
border: 1px dotted blue;
padding:1em;
}
</style>
<foreignObject class="node" x="16" y="22" width="400" height="100">
<body xmlns="http://www.w3.org/1999/xhtml">
<div>Some text with a superscript <sup>1</sup> and a subscript <sub>2</sub></div>
</body>
</foreignObject>
</svg>
Example for wrapping multi-line text in svg just like in HTML
svg {
border: 1px solid black;
}
svg div{
border: 1px dotted blue;
padding: 1em;
}
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="500">
<foreignObject class="node" x="46" y="22" width="200" height="500">
<body xmlns="http://www.w3.org/1999/xhtml">
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus tincidunt dignissim nibh a facilisis. Phasellus pretium nisl vel turpis suscipit, quis posuere quam laoreet. Vestibulum fringilla porttitor felis, non lacinia dolor mattis vitae. Donec gravida et purus eu pellentesque. Nam consequat nisl id velit interdum eleifend. Mauris nulla turpis, sollicitudin in vestibulum nec, ornare quis lacus. </div>
</foreignObject>
</svg>

I have tried many things to get the superscript, and it is not supported the same across browsers.
For Firefox...
tspan.sup { font-size: 50%; dominant-baseline: hanging; }
For Chrome (and Inkscape)...
tspan.sup { font-size: 50%; baseline-shift: super; }
When both styles are used, Chrome will apply the baseline-shift, but it will not be entirely superscript. Inkscape will apply the baseline-shift correctly even with dominant-baseline present. It may be a case of choosing the browser you want to support.
And a non-CSS method.
<text x="0" y="14">Some text<tspan dy ="-10">1</tspan></text>
# If there is more text is after the tspan, do the following.
<text x="0" y="14">Some text<tspan dy ="-10">e</tspan> <tspan dy="10">with more text.</tspan></text>

Related

Apply css only on the wrapped part of text

I have an HTML component that has an image floating to the left and text on the right. When the text's height is larger than the image, the text will wrap to the left. I want to add some padding between the image and the wrapped text. I could add a bottom padding to the image, but I don't want the padding to show up when the text is not wrapped. Here is what the component should look like when the text is no wrapped. The image should not have a bottom padding:
Here is what it should look like when the text is wrapped. There should be some padding between the image and the wrapped text:
Is there a way to do this through css?
An idea in case the image height is fixed or known:
.container {
border:2px solid;
min-height:200px; /* same as image height */
font-size:19px;
}
.container img {
float:left;
margin:0 20px 20px 0;
}
<div class="container">
<img src="https://picsum.photos/id/1014/200/200" > Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque fermentum quis mi vitae molestie. Sed scelerisque fringilla interdum. Duis ac purus nisl. Nulla vehicula vehicula turpis id convallis. Etiam nec nisl nibh. Mauris lorem mauris, vehicula nec massa in, accumsan egestas eros. Integer vehicula nulla sed enim laoreet maximus. Vestibulum at interdum sem. Sed interdum volutpat massa,
</div>
Yes, you can do it. Follow this example for HTML and css.
body {
margin: 20px;
text-align: center;
}
img {
float: left;
margin: 0px 10px 5px 10px;
}
p {
text-align: justify;
font-size: 20px;
}
<!DOCTYPE html>
<html>
<head>
<title>
Wraping an Image with the text
</title>
</head>
<body>
<div class="square">
<div>
<img src= "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/1024px-Image_created_with_a_mobile_phone.png" alt="Longtail boat in Thailand" width="300px">
</div>
<p>
How many times were you frustrated while looking
out for a good collection of programming/algorithm
/interview questions? What did you expect and what
did you get? This portal has been created to
provide well written, well thought and well
explained solutions for selected questions.
An IIT Roorkee alumnus and founder of GeeksforGeeks.
He loves to solve programming problems in most
efficient ways. Apart from GeeksforGeeks, he has
worked with DE Shaw and Co. as a software developer
and JIIT Noida as an assistant professor. It is a
good platform to learn programming. It is an
educational website. Prepare for the Recruitment
drive of product based companies like Microsoft,
Amazon, Adobe etc with a free online placement
preparation course.
</p>
</div>
</body>
</html>

CSS Flex dynamic horizontal width based on nested element width

I'm trying to create the following layout using CSS Flex. It seems simple but there's a tricky part to it which I will explain below.
HTML:
<div class="flex">
<div class="icon-col">
<div class="icon" style="max-width:120px;">
<svg>image code here...</svg>
</div>
</div>
<div class="text-col">
<h4>Awesome Design</h4>
<p>Nullam vel sem. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Curabitur blandit mollis lacus. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc.</p>
</div>
</div>
CSS:
.flex {
display: flex;
flex-direction: row;
}
.icon-col, .text-col {
flex: 1;
}
.icon {
width: 100%;
}
Codepen preview: https://codepen.io/anon/pen/KEjJeO
As you can see in the preview, there is too much space between the icon and the text. The icon has to be 120px as specified in the inline CSS and the width of the text column should grow or shrink based on the icon size.
Try tricky part:
The icon has a dynamic width.
I can define a width for the icon using only an inline style in the HTML, in the .icon element as seen above in the HTML.
I have no control over the .icon-col element as far as adding a dynamic width to it. It would have been easy if I could just add the width to .icon-col.
I also can't add a width to .text-col because it has to resize automatically based on the icon size.
How can .icon-col be the same width as its child element .icon and have the text column resize automatically?
You can group and move things around but its just to get an idea.
.flex2 {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
background-color: blue;
}
.icon-col {
flex: 1 1 20%;
background-color: #ff0000;
position: relative;
padding: 20px;
}
.abacadabra {
width: 120px;
max-width: 120px;
position: relative;
float: right;
right: 5px
}
.text-col {
flex: 1 1 80%;
background-color: #ffff00;
padding: 20px
}
<div class="flex2">
<div class="icon-col">
<div class="abacadabra">
<svg aria-hidden="true" data-prefix="fas" data-icon="tools" class="svg-inline--fa ugbfa-tools fa-w-16 " role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M501.1 395.7L384 278.6c-23.1-23.1-57.6-27.6-85.4-13.9L192 158.1V96L64 0 0 64l96 128h62.1l106.6 106.6c-13.6 27.8-9.2 62.3 13.9 85.4l117.1 117.1c14.6 14.6 38.2 14.6 52.7 0l52.7-52.7c14.5-14.6 14.5-38.2 0-52.7zM331.7 225c28.3 0 54.9 11 74.9 31l19.4 19.4c15.8-6.9 30.8-16.5 43.8-29.5 37.1-37.1 49.7-89.3 37.9-136.7-2.2-9-13.5-12.1-20.1-5.5l-74.4 74.4-67.9-11.3L334 98.9l74.4-74.4c6.6-6.6 3.4-17.9-5.7-20.2-47.4-11.7-99.6.9-136.6 37.9-28.5 28.5-41.9 66.1-41.2 103.6l82.1 82.1c8.1-1.9 16.5-2.9 24.7-2.9zm-103.9 82l-56.7-56.7L18.7 402.8c-25 25-25 65.5 0 90.5s65.5 25 90.5 0l123.6-123.6c-7.6-19.9-9.9-41.6-5-62.7zM64 472c-13.2 0-24-10.8-24-24 0-13.3 10.7-24 24-24s24 10.7 24 24c0 13.2-10.7 24-24 24z"></path></svg>
</div>
</div>
<div class="text-col">
<h4>Awesome Design</h4>
<p>Nullam vel sem. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Curabitur blandit mollis lacus. Aenean tellus metus, bibendum sed, posuere ac, mattis non, nunc.</p>
</div>
</div>

svg clippath on a div that contain other divs (no css:clip-path)

I am actually trying to make something that sounded very simple, but apparently it isn't
I have 2 div containing informations (text images etc). I want to put a clipping mask (circle shape) over those so if I put my mouse over it, it changes to a rectangle and reveal the whole content (that effect is pretty common no?) But apparently I can't even perform the task of puting a circle clipping mask over my divs
here's what I tried
body {
background-color:#000;
}
<svg>
<defs>
<clipPath viewBox="0 0 100 100" id="promopath" >
<circle cx="100" cy="100" r="75" />
</clipPath>
</defs>
<use clip-path='url(#promopath)' xlink:href='#promo_bubble' fill='white' />
</svg>
<div class='promo_wrapper' id='promo_bubble'>
<div class='promo_holder'><img src='https://picsum.photos/200/300'></div>
<div class='promo_holder'><img src='https://picsum.photos/200/300'></div>
</div>
Codepen here if you want to play around
I can make a mask over a simgle image, but not for a whole container like in my example
I don't want to use clip-path because of edge and internet explorer support
Thanks for your help
You can consider a trick using border-radius without any complex code or the use of SVG:
.box {
margin: 100px;
width: 50px;
height: 50px;
border: 2px solid;
border-radius: 50%;
overflow:hidden;
background:#fff;
transition:1s all;
}
.container {
width:200px;
height:200px;
border:1px solid;
transform:translate(calc(25px - 50%),calc(25px - 50%));
transition:1s all;
}
img {
float:left;
}
.box:hover {
border-radius:0;
width: 200px;
height: 200px;
margin:0;
}
.box:hover .container{
transform:translate(0);
}
body {
margin:0;
background:pink;
}
<div class="box">
<div class="container">
<img src="https://picsum.photos/100/100?image=1069" > Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut et felis ligula. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Morbi tempor pellentesque lacus id ullamcorper.
</div>
</div>

Is there any way to use css class in foreignObject of svg which be drawn into canvas?

Is there any way to make my html use class in foreignObject of svg? For now, it can just use style attribute in every tag but that's too bad :(
I look up some converters which convert class in html to inline style, but both of them have all kinds of problems.
So is there any better solution?
----------------------------------edit-----------------------------
Sorry, I miss some words, I want to insert the svg into canvas(by converting it to Blob and then call ctx.drawImage)
You have to add a style tag inside that svg tag. Any style given in that style tag will be available inside that foreignObject. For Example,
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<style>
.container {
color: white;
font: 18px serif;
height: 100%;
overflow: auto;
}
</style>
<polygon points="5,5 195,10 185,185 10,195" />
<!-- Common use case: embed HTML text into SVG -->
<foreignObject x="20" y="20" width="160" height="160">
<!--
In the context of SVG embedded in an HTML document, the XHTML
namespace could be omitted, but it is mandatory in the
context of an SVG document
-->
<div xmlns="http://www.w3.org/1999/xhtml" class="container">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Sed mollis mollis mi ut ultricies. Nullam magna ipsum,
porta vel dui convallis, rutrum imperdiet eros. Aliquam
erat volutpat.
</div>
</foreignObject>
</svg>
source MDN Web Docs - foreignObject

Multi-column div with image

I'm trying style a 2-col div with an image the width of one column in the first column, using the CSS3 property column-count. For browsers that CAN handle CSS3, it should look like this:
img col
col col
col col
col col
However, for browsers that cannot read the CSS, instead of having the image stuck in the top left with the text starting on the next line, I want it floating, like this:
img texttextte
xttexttexttext
texttetexttext
Currently, I have this for the image in question, which lays out exactly what I want for browsers that CAN'T support CSS3:
display: inline;
float: left;
-webkit-column-span: in-column;
-moz-column-span: in-column;
But for browsers that can support it, it appears like this, with the image taking up a column all to itself:
img col col
col col
col col
col col
...which is not what I want at all. How do I get that image to float, with or without columns?
EDIT:
Here is the HTML:
<div id="content">
<h2>Title here</h2>
<img src="/static/images/img01.jpg" width="200" height="152" />
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nam porttitor urna sit amet est pulvinar congue. Integer
lacinia dictum enim, non molestie turpis volutpat et. Praesent
pretium accumsan sapien, porttitor rhoncus augue porta ac.
Quisque fermentum enim quis magna condimentum a lobortis urna
accumsan. Integer viverra tristique turpis, sed fermentum
lorem hendrerit vitae.</p>
</div>
Here is the not-quite-working CSS so far:
#content {
width: 600px;
-moz-column-count: 2;
-webkit-column-count: 2;
-moz-column-gap: 18px;
-webkit-column-gap: 18px;
}
#content img {
display: inline;
float: left;
-webkit-column-span: in-column;
-moz-column-span: in-column;
}
I feel like a floating, inline image shouldn't behave that way in a column.
You could try this...
<img src="/static/images/img01.jpg" width="200" height="152" style="float: left;"/>
...as an inline style (better still as a class in an external style sheet) or with the good old align attribute ...
<img align="left" src="/static/images/img01.jpg" width="200" height="152" />
...I hope this helps.
You can just put the image in the p tag. Your size for the columns and the image you have preset so you're good. I've done this no problem, the only thing you can't do is have the image span multiple columns.