How to make arc shapes with CSS3? - html

I'm trying to achieve following look, with pure css:
Where each white arc is a different element, say span. I know we can make round shapes with css, but how can it be turned into arc sort of shape?

With the following HTML:
<div id="arcs">
<div>
<div>
<div>
<div></div>
</div>
</div>
</div>
</div>
And the CSS:
#arcs div {
border: 2px solid #000; /* the 'strokes' of the arc */
display: inline-block;
min-width: 4em; /* the width of the innermost element */
min-height: 4em; /* the height of the innermost element */
padding: 0.5em; /* the spacing between each arc */
border-radius: 50%; /* for making the elements 'round' */
border-top-color: transparent; /* hiding the top border */
border-bottom-color: transparent;
}
#arcs div {
border: 2px solid #000;
/* the 'strokes' of the arc */
display: inline-block;
min-width: 4em;
/* the width of the innermost element */
min-height: 4em;
/* the height of the innermost element */
padding: 0.5em;
/* the spacing between each arc */
border-radius: 50%;
/* for making the elements 'round' */
border-top-color: transparent;
/* hiding the top border */
border-bottom-color: transparent;
}
<div id="arcs">
<div>
<div>
<div>
<div></div>
</div>
</div>
</div>
</div>
JS Fiddle demo.

SVG Approach:
I would recommend you to use SVG to draw such shapes:
In the example below I've used SVG's path element to draw an arc. This element takes single attribute d to describe the shape structure. d attributes takes a few commands and corresponding necessary parameters.
I've used only 2 path commands:
M command is used to move the pen to a specific point. This command takes 2 parameters x and y and usually our path begins with this command. It basically defines starting point of our drawing.
A command which is used to draw curves and arcs. This commands takes 7 parameters to draw an arc / curve. A detailed explanation of this command is Here.
Screenshot:
Useful Resources:
Specification
MDN
Working Example:
svg {
width: 33%;
height: auto;
}
<svg viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg">
<defs>
<g id="arcs" fill="none" stroke="#fcfcfc">
<path d="M80,80 A100,100,0, 0,0 80,220" stroke-width="4" />
<path d="M90,90 A85,85,0, 0,0 90,210" stroke-width="3.5" />
<path d="M100,100 A70,70,0, 0,0 100,200" stroke-width="3" />
<path d="M110,110 A55,55,0, 0,0 110,190" stroke-width="2.5" />
</g>
</defs>
<rect x="0" y="0" width="300" height="300" fill="#373737" />
<use xlink:href="#arcs" />
<use xlink:href="#arcs" transform="translate(300,300) rotate(180)" />
</svg>

Related

Start svg polyline exactly at right border of span element

I have a simple html file containing an SVG polyline:
Here's my code:
span {
border: 1px solid red;
}
polyline{
fill:none;
stroke:red;
stroke-width:3
}
<p>A block element containing an <span>inline element</span></p>
<svg height="200" width="500">
<polyline points="0,0 20,0 40,25" />
</svg>
I would like to start the polyline exactly at the midpoint of my span's right border. How can I do that?
This is a very basic idea: you give the svg position:absolute and the same size as the html element overlapped. You calculate the bounding client rect of the span and the position of the point where the polyline shpuld begin. Ypu either translate the polyline or you rewrite the points attribute so that it begins where you want it
let bcr = sp.getBoundingClientRect();
poly.setAttribute("transform",`translate(${bcr.x+bcr.width},${bcr.y+bcr.height/2})`)
svg {
outline: solid;
position: absolute;
top:0;left:0;
}
div {
width: 500px;
height: 200px;
}
span {
border: 1px solid red;
}
polyline {
fill: none;
stroke: red;
stroke-width: 3;
}
<div>
<p>A block element containing an <span id="sp">inline element</span></p>
</div>
<svg height="200" width="500">
<polyline id="poly" points="0,0 20,0 40,25" />
</svg>

Alternatively clicking on two overlapping svgs

I'm trying to create a buttons panel for a web page. I made the buttons with .svg files. Using margins an other css attributes i got them to the position shown in the code.
My problem:
I can't make both buttons fully clickable, specifically, I can use the orange part just fine, but the bottom half of the white circle, which is overlapping the orange's bounding-box, I cannot click on ,the top area is good.
Of course i wanna be able to successfully click anywhere in the white or the orange, without the overlapping interfering.
I've been reading on pointer events and figure they are the solution, but i can't figure out where (html or css) to use them or how. Also i'm not sure which property would be correct.
How the buttons are working
<!--my html code-->
<div id="brand">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 106 106">
<defs>
<style>.cls-1{fill:#ffffff;}</style>
</defs>
<a xlink:href="index.html">
<path class="cls-1" d="M67.78,52.28a5.58,5.58,0,0,0-6,0,6,6,0,0,0-2.11,2.45,9.11,9.11,0,0,0,0,7.42,6,6,0,0,0,2.11,2.45,5.58,5.58,0,0,0,6,0,6.05,6.05,0,0,0,2.11-2.45,9.11,9.11,0,0,0,0-7.42A6.05,6.05,0,0,0,67.78,52.28Z"/><path class="cls-1" d="M53,0a53,53,0,1,0,53,53A53.06,53.06,0,0,0,53,0ZM77.67,78.67a10,10,0,0,1-4.3.91A13.53,13.53,0,0,1,69.14,79a12.7,12.7,0,0,1-3.74-2.09,34.09,34.09,0,0,1-4.26-4.15A13.74,13.74,0,0,1,55.34,70a14.09,14.09,0,0,1-3.91-5A15,15,0,0,1,50,58.44L50,45.66,43.86,55.92H39.69L33.61,46.1V58.44H25v-28h7.77L41.9,45.34,50.79,30.4h7.77L58.6,45a15.72,15.72,0,0,1,6.2-1.21,15.38,15.38,0,0,1,7.6,1.88,13.68,13.68,0,0,1,5.27,5.24,15,15,0,0,1,1.91,7.56A14.78,14.78,0,0,1,77.3,66.6a13.64,13.64,0,0,1-6.17,5.24,3.52,3.52,0,0,0,1.14.9,3.13,3.13,0,0,0,1.29.26,4.94,4.94,0,0,0,3.63-1.81L81,76A9,9,0,0,1,77.67,78.67Z"/>
</a>
</svg>
</div>
<div id="reserve">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 944.38 115.07">
<defs>
<style>.cls-2{fill:#ff7800;}</style>
</defs>
<a xlink:href="reserve.html">
<path class="cls-2" d="M494.41,80.8h-3.78v7h3.78a4.7,4.7,0,0,0,3.15-.91,3.23,3.23,0,0,0,1.07-2.59,3.27,3.27,0,0,0-1.07-2.61A4.65,4.65,0,0,0,494.41,80.8Z"/><path class="cls-2" d="M400.62,80.8h-3.77v7h3.77a4.73,4.73,0,0,0,3.16-.91,3.23,3.23,0,0,0,1.07-2.59,3.27,3.27,0,0,0-1.07-2.61A4.68,4.68,0,0,0,400.62,80.8Z"/><path class="cls-2" d="M940.67,10a55.59,55.59,0,0,0,3.71-10H535.66A63.67,63.67,0,0,1,474,59.85h-3.54A63.67,63.67,0,0,1,408.72,0H0A55.59,55.59,0,0,0,3.71,10H364.28V20H9.42a68.63,68.63,0,0,0,8.32,10H364.28V40H30.75C40.78,45.88,53.9,50,71,50H364.29V98.82a16.24,16.24,0,0,0,16.25,16.25h183.3A16.25,16.25,0,0,0,580.1,98.82V50H873.4c17.08,0,30.2-4.12,40.23-10H580.1V30H926.64A68.52,68.52,0,0,0,935,20H580.1V10ZM404.92,99.48l-4.36-6.39h-3.71v6.39h-6.8v-24h11a13.71,13.71,0,0,1,5.66,1.08,8.75,8.75,0,0,1,3.8,12.37,8.38,8.38,0,0,1-3.49,3l5.19,7.55Zm29.84,0h-19.3v-24h18.85V80.7H422.19v4h10.68v5.08H422.19v4.4h12.57Zm21.67-3.36a8.25,8.25,0,0,1-3.61,2.79,14.55,14.55,0,0,1-5.84,1,22.23,22.23,0,0,1-5.66-.72,14,14,0,0,1-4.47-1.92l2.23-5A14.38,14.38,0,0,0,442.83,94a14.06,14.06,0,0,0,4.19.65c2.61,0,3.91-.65,3.91-2a1.62,1.62,0,0,0-1.11-1.53,21.14,21.14,0,0,0-3.59-1,35.84,35.84,0,0,1-4.54-1.25,7.63,7.63,0,0,1-3.12-2.15,5.79,5.79,0,0,1-1.31-4,6.84,6.84,0,0,1,1.21-4,8,8,0,0,1,3.59-2.8,14.69,14.69,0,0,1,5.85-1,20.9,20.9,0,0,1,4.67.53,14.31,14.31,0,0,1,4.05,1.57l-2.09,5a14.06,14.06,0,0,0-6.66-1.85,5.63,5.63,0,0,0-3,.6,1.79,1.79,0,0,0-.92,1.56,1.55,1.55,0,0,0,1.09,1.45,20.1,20.1,0,0,0,3.54,1,34.24,34.24,0,0,1,4.55,1.25,8,8,0,0,1,3.13,2.13,5.72,5.72,0,0,1,1.32,4A6.8,6.8,0,0,1,456.43,96.12Zm23.62,3.36h-19.3v-24h18.86V80.7H467.48v4h10.68v5.08H467.48v4.4h12.57Zm18.65,0-4.36-6.39h-3.71v6.39h-6.8v-24h11a13.71,13.71,0,0,1,5.66,1.08,8.42,8.42,0,0,1,3.71,3.09,8.5,8.5,0,0,1,1.31,4.73,8.41,8.41,0,0,1-1.22,4.55,8.32,8.32,0,0,1-3.49,3L506,99.48Zm24.62,0h-6.7l-10.26-24h7.34l6.53,15.66,6.66-15.66h6.73Zm31,0H535v-24h18.85V80.7H541.76v4h10.68v5.08H541.76v4.4h12.57Z"/>
</a>
</svg>
</div>
<!--my css (wide interface being a mayor div that encases all the buttons)-->
#brand { margin: auto; }
#reserve { margin: auto; }
#media screen and (min-width: 751px) {
#brand { width: 11%; overflow: hidden; }
#reserve { width: 95%; margin-top: -5.4%; overflow: hidden; }
#wide-interface { overflow: hidden; white-space: nowrap; letter-spacing: 5px; text-align: center; }
}
You need to apply a clipPath to the white circle to restrict that shape.
By default, pointer-events must not be dispatched on the clipped
(non-visible) regions of a shape.
You will need to adjust the radius and coordinates but something like;
<clipPath id="myClip">
<circle cx="53" cy="25" r="25" />
</clipPath>

HTML arc sector with inline style

I would like to use HTML + CSS to draw a arc sector with fixed radix and length (e.g. 30px radius and 70% length).
I found so far most of the solution is to combined two pictures with position:absoulte. Unfortunately, my html codes will be embedded as an email template to send out, and I found that Gmail does not support absolute position. And that is also the reason why I would like to use inline style rather than header css.
Related question here:
HTML5 / CSS3 Circle with Partial Border
The similar output I am looking for.
http://dabblet.com/gist/3949571
Any help for it?
I'd use an SVG.
svg {
width: 150px;
height: 150px;
}
circle.inner {
stroke: rebeccapurple;
stroke-width: 3;
stroke-dasharray: 39% 139%;
stroke-dashoffset: 78%;
fill: pink;
}
<svg viewbox="0 0 100 100">
<circle class="inner" cx="40" cy="40" r="25" />
</svg>
you can use transparent borders and inset shadow to draw bg color :
/*demo*/
div {
display:flex;
align-items:center;
justify-content:center;/* center content not text */
text-align:center;
}
<div style="
box-sizing:border-box;
padding:1px;
margin:5px;
height:200px;
width:200px;
border:solid 20px transparent;
border-top-color:blue;
box-shadow:inset 0 0 0 100px lightblue;
border-radius:100%;"
>Some text <br/> too?</div>

Positioning overlapping SVGs inside a block element

I have a couple of circle SVGs that I am stacking on top of one another. In order to do that I have assigned them an absolute position style. My problem is I can't seem how to get the stacked SVGS to display within a block element, such as a DIV tag, when I do so.
This is what I have so far:
.card {
background-color:white;
border: 1px solid gray;
border-top: 10px solid gray;
padding:20px;
box-shadow: 1px 1px 1px #888888;
margin-bottom: 30px;
}
circle {
fill: transparent;
stroke-width: 30;
}
svg {
width: 150px;
height: 150px;
position: absolute;
}
<P>I would like to have the three pie charts stack on top of them like they are doing, but I would like for them to be inside the card (DIV).</P>
<DIV class="PieChart" style="stroke-dasharray: 377 377; stroke: #80F162;">
<svg>
<circle r="60" cx="50%" cy="50%"/>
</svg>
</DIV>
<DIV class="PieChart" style="stroke-dasharray: 255 377; stroke: #F06161;">
<svg>
<circle r="60" cx="50%" cy="50%"/>
</svg>
</DIV>
<DIV class="PieChart" style="stroke-dasharray: 189 377; stroke: #F4F464;">
<svg>
<circle r="60" cx="50%" cy="50%"/>
</svg>
</DIV>
An example of what I have so far can be found here:
https://jsfiddle.net/e82agLn2/
Any help would be greatly appreciated.
Thanks!
The reason this is happening is that you have 3 svg nodes that you're overlapping using position:absolute (and absolute positioning takes svg elements out of the wrapping div's flow);
You could use one svg tag( without position:absolute ) and use g tags to group the elements_
fiddle

Create three lines following element using pseudo class/elements

I'm trying to get a heading element on my page to look like:
I saw the steps shown at CSS: :before and :after pseudo elements in practice (see heading 'Styling titles') which displays a single line before and after the heading element. I liked that idea and wanted to expand it out to display three lines as per the sample image. Unlike image I was hoping for the lines to be thinner and not take up the full height space available but that's all I could mock up with limited tools/skills.
My issue is not getting three lines, but rather aligning each of those lines to their intended place. Currently they mess up and stack in an unexpected way (at least unexpected from my understanding).
Here is a JsFiddle showing my progress so far. I've created the h1 for text and two spans either side of the text but within the h1. My reasoning for this was to remove the single line from the h1 and apply the three lines via each span utilising pseudo-elements :after and :before for two of them.
Not sure where I have gone wrong or if it is even possible. I have complete access to HTML and CSS so the structure and styles are not locked down.
Let me know if I haven't been clear.
You can do it using two spans.
.long {
position: relative;
width: 100%;
}
.long:after, .long:before {
content: '';
position: absolute;
height: 3px;
width: 30px;
background: black;
top: 50%;
left: -34px;
}
.long:before {
left: calc(100% + 4px);
}
.title {
position: relative;
font-size: 50px;
margin-left: 40px;
}
.title:after, .title:before {
content: '';
position: absolute;
height: 20%;
width: 20px;
border-top: 3px solid black;
border-bottom: 3px solid black;
top: calc(100% - 31.2%*2);
right: -24px;
}
.title:before {
right: calc(100% + 4px)
}
<span class="title"><span class="long">text</span></span>
Also, possible with svg if you want round corners.
<svg width="170" height="50" viewBox="-10 0 170 50">
<defs>
<line id="small" x1="3" y1="3" x2="20" y2="3" stroke="black" stroke-width="3" stroke-linecap="round" />
<line id="large" x1="3" y1="3" x2="30" y2="3" stroke="black" stroke-width="3" stroke-linecap="round" />
</defs>
<text x="75" y="35" text-anchor="middle" font-size="50">text</text>
<use transform="translate(5,10)" xlink:href="#small" />
<use transform="translate(-5,17)" xlink:href="#large" />
<use transform="translate(5,24)" xlink:href="#small" />
<use transform="translate(125,10)" xlink:href="#small" />
<use transform="translate(125,17)" xlink:href="#large" />
<use transform="translate(125,24)" xlink:href="#small" />
</svg>
You could use a CSS background image, or gradient to achieve the same effect.
The CSS background will be something along the lines of:
background:linear-gradient(to bottom, #fff 0%, #fff 20%, transparent 20%, transparent 40%, #fff 40%, #fff 60%, transparent 60%, transparent 80%, #fff 80%, #fff 100%);
Why not create a left and right image and display it with the :before and :after like you are but instead of setting content: add background: url('img_left.png');?
Here is a Fiddle to show what I mean.