Creating a transparent inner notch? - html

I know how to create a notch on the outside like:
div:after {
content: '';
display: block;
width: 20px;
height: 20px;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
But I can't figure out how to solve this thingy using CSS only:
The notch has to be inside of the container and it has to be transparent. So the above solution or an image won't solve it.
Maybe this can be created using SVG?
Edit
What I tried is this:
body {
background: #eee;
}
div {
position: relative;
height: 100px;
width: 200px;
background: #ccc;
}
div:after {
content: '';
position: absolute;
display: block;
top: 40px;
right: -10px;
width: 20px;
height: 20px;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
background: #eee;
}
But this is clearly no soultion, because the pseudo element is not tranparent.

You cannot do this with pure CSS as clipping is not fully supported yet in all browsers (if cross-compatibility is important).
You would need to combine SVG clipping paths with CSS clipping and would end up with a not so elegant solution.
What you can do however is to create a background image using canvas. Canvas is supported in all the major HTML5 capable browsers. The backdraw with canvas is that you need to do a little more coding to create the shape. Optional an image could have been used instead but using canvas allow you to keep everything sharp (and not blurry as with an image when it is stretched).
The following solution will produce this result (I added red border to show the transparent region). You can tweak the parameters to get it look exactly as you need it to look and extend it with arguments to define size of the notch, width of transparent area etc. The code automatically adopts to the size of the element given as argument.
To add a notch simply call:
addNotch(element);
ONLINE DEMO HERE
The code is straight-forward and performs fast:
function addNotch(element) {
/// some setup
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
/// get size of element in pixels
cs = window.getComputedStyle(element),
w = parseInt(cs.getPropertyValue('width') || '0', 10),
h = parseInt(cs.getPropertyValue('height') || '0', 10),
/// pre-calculate some values
hh = h * 0.5,
nw = 20, /// notch size
nh = nw * 0.5;
canvas.width = w;
canvas.height = h;
/// draw the main shape
ctx.moveTo(0, 0);
ctx.lineTo(w - nw, 0);
ctx.lineTo(w - nw, hh - nh);
ctx.lineTo(w - nw - nh, hh);
ctx.lineTo(w - nw, hh + nh);
ctx.lineTo(w - nw, h);
ctx.lineTo(0, h);
ctx.closePath();
ctx.fillStyle = '#7c7058';
ctx.fill();
/// draw the white arrow
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = '#eee';
ctx.moveTo(w - nw - nw * 0.33, hh - nw * 0.75);
ctx.lineTo(w - nw - nw * 1.1, hh);
ctx.lineTo(w - nw - nw * 0.33, hh + nw * 0.75);
ctx.stroke();
/// convert canvas to image and set background of element
/// with this image
element.style.background = 'url(' + canvas.toDataURL() +
') no-repeat left top';
}

Here's an example using SVG clipping.
jsFiddle Demo
<div></div>
<svg>
<defs>
<clipPath id="clipping">
<polygon points="
0 0, 202 0,
202 36, 185 50, 202 64,
202 102, 0 102" />
</clipPath>
</defs>
</svg>

Try this fiddle out, it should set you on your way for what you're looking for.
#notched {
width: 0px;
height: 0px;
border-right: 60px solid transparent;
border-top: 60px solid #d35400;
border-left: 60px solid #d35400;
border-bottom: 60px solid #d35400;
}
Updated fiddle

You can use the :before for mask and after selector for the border, just set border-lef and border-bottom property.
div:before {
content: '';
position: absolute;
display: block;
top: 40px;
right: -10px;
width: 20px;
height: 20px;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
background: #eee;
}
div:after {
content: '';
position: absolute;
display: block;
top: 38px;
right: -5px;
width: 20px;
height: 21px;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
background: transparent;
border-left: 2px solid #eee;
border-bottom: 2px solid #eee;
}
the result:
jsFiddle

Related

How to use WebGL to render a button background?

Let's say that I have a GL shader I'd want to use as an HTML button background (it's a pretty animated gradient). How can I achieve that?
I can think of setting the background to a texture and rendering the shader to this texture. Is that fundamentally possible?
Using a canvas inside a button is the most logical way to go, note that this is just an example and not a shader, but we use the canvas to render WebGL so it can be slightly different for your case.
var c = document.getElementsByTagName("canvas")[0];
var ctx = c.getContext("2d");
// Create gradient
var grd = ctx.createLinearGradient(0, 0, 200, 0);
grd.addColorStop(0, "red");
grd.addColorStop(1, "green");
// Fill with gradient
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 400, 200);
button {
position: relative;
background-color: transparent;
border: none;
outline: none;
padding: 8px;
}
button > div {
position: relative;
z-index: 1;
}
canvas {
position: absolute;
top: 0;
right: 0;
width: 100%;
height: 100%;
z-index: -1;
pointer-events: none;
}
<button>
<canvas></canvas>
<div>Fancy Button</div>
</button>

How i can create curved 3d objects with html and css

I have an html/css 3d object as in picture 2. I want to make it curve a little bit as in picture 1
Does someone have an idea perhaps how it could be achieved Or if there is any other technology by which I can shape these 3d objects ?
This is the code for my object in the picture 2:
.container {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.cube {
background: #dc2e2e;
width: 200px;
height: 50px;
position: relative;
margin: 50px;
transform: rotate(32deg);
}
.cube::before {
content: '';
display: inline-block;
background: #f15757;
width: 200px;
height: 2px;
transform: skewX( -80deg);
position: absolute;
top: -2px;
left: 6px;
}
.cube::after {
content: '';
display: inline-block;
background: #9e1515;
width: 12px;
height: 50px;
transform: skewY(-10deg);
position: absolute;
top: -1px;
left: 100%;
}
<div class="container">
<div class="cube"></div>
</div>
Creating an arc out of a div element is not so straightforward . Also using div tag to create shapes and graphics is not a good way instead you should use Scalable Vector Graphics(SVG), HTML Canvas, WebGL or any other JS libraries.
Using div tag you can create a bottom arc by adding bottom border radius:
.cube {
background: #dc2e2e;
width: 200px;
height: 50px;
position: relative;
margin: 50px;
box-shadow: 0px 10px 16px -6px black;
border-bottom-left-radius: 50%;
border-bottom-right-radius: 50%;
}
<div class="container">
<div class="cube"></div>
</div>
But you can't achieve a top arc using the border top radius because using it will create an arc in opposite direction and thus create an oval instead of an arch.
One thing you can do is to overlay the upper part of the rectangle with another div tag of white color to create an arch like effect.
.arch {
width: 200px;
overflow: hidden;
}
.lowerarc {
width: 240px;
position: relative;
right: -10px;
left: -20px;
height: 80px;
background-color: black;
border-bottom-left-radius: 50%;
border-bottom-right-radius: 50%;
}
.upperarc {
height: 80px;
position: relative;
width: 240px;
top: -120px;
right: -10px;
left: -20px;
background-color: white;
border-bottom-left-radius: 50%;
border-bottom-right-radius: 50%;
}
<div class="arch">
<div class="lowerarc"></div>
<div class="upperarc"></div>
</div>
But it doesn't look good. so using div is probably not the best way to get the desired result.
Try using SVG instead:
In this example below we create an arch using lines and curves by plotting pixel values and filling the shape with a specific color.
M means move to, L to create a line, Q to draw curves, and z to close the path and the number corresponding to it are the values in pixel
<svg width="200">
<path d="M0,0 L0,50 Q100,80 200,50 L200,0 Q100,25 0, 0z" fill="black" />
</svg>
In this code below, we just create a curve line but with a 50px thickness.
<svg viewBox="0 0 1000 400">
<path d="M 60,250 C 60,150 150,50 250,50" fill="none"
stroke="green" stroke-width="50"></path>
</svg>
Use Canvas:
Canvas is similar to Svg but it uses javascript to create path and graphics.
var canvas = document.getElementById('canvas');
var c = canvas.getContext('2d');
c.beginPath();
c.moveTo(60, 0);
c.lineTo(10, 0);
c.quadraticCurveTo(0, 170, 170, 250);
c.lineTo(195, 210);
c.quadraticCurveTo(50, 150, 60, 0);
c.fill();
<canvas id="canvas" width="622" height="1080"></canvas>
While SVG and Canvas are used to create 2D graphics only,but still you can use 2D objects together to create a 3D like illusion.
var canvas = document.getElementById('canvas');
var c = canvas.getContext('2d');
c.fillStyle="rgba(0, 0, 25, 0.7)";
c.beginPath();
c.moveTo(10, 0);
c.lineTo(0, 5);
c.quadraticCurveTo(-10, 180, 170, 260);
c.lineTo(195, 220);
c.lineTo(195, 210);
c.quadraticCurveTo(30, 250, 60, 0);
c.fill();
c.fillStyle="rgb(200, 210, 200)";
c.beginPath();
c.moveTo(60, 0);
c.lineTo(10, 0);
c.quadraticCurveTo(0, 165, 170, 250);
c.lineTo(195, 210);
c.quadraticCurveTo(50, 135, 60, 0);
c.fill();
<canvas id="canvas" width="622" height="1080"></canvas>
<script src="main.js">
</script>
SVG and Canvas codes looks scary but it is not as difficult as it looks like. You can read documentations or watch Youtube tutorials to learn it properly.
Making curved 3d objects in pure html/css is not very easy but it is doable. There a few techniques to do it but you will need to understand exactly what you want and how to alter the number to achieve it.
You can stack multiple div elements to create a curved 3d effect and then offset the z axis for each one. Essentially you are just stacking lots of elements together to give the illusion of a curved 3d object. In the below links I use radial gradient.
I would recommend using a pre-proccessor like SCSS for this as it allows you to run a loop to offset each element cutting out a lot of code you would have to write for each element. Also keep in mind if you intend to animate this after then that will be very taxing on the processing depending on device. If you are trying to make it static then it shouldn't be an issue.
SCSS
#for $i from 1 through 20 {
$color: red;
&:nth-child(#{$i}) {
position: absolute;
width: $width;
height: $height;
list-style: none;
background: rgb(0, 0, 0);
background: radial-gradient(
circle at 50% 150%,
rgba(0, 0, 0, 0) 0%,
rgba(0, 0, 0, 0) 60%,
darkred 60%,
darkred 70%,
rgba(0, 0, 0, 0) 70%,
rgba(0, 0, 0, 0) 100%
);
transform: translateZ(-20px + (0.8px * ($i - 1)));
filter: blur(0px) contrast(200%);
}
simple curves example 1 https://codepen.io/jfirestorm44/pen/MWmKraz?editors=0100
complex art example 2 https://codepen.io/jfirestorm44/pen/qBZYQBL
Like I said about performance; Example 2 will take some processing power and may lag. The object can be rotate by clicking.
I'd like to add to #Miran Firdausi's answer about SVGs (but I can't comment yet). A good way to create SVGs and then "hard code" them into CSS is to use any vector paint program (such as Inkscape) to draw exactly what you want, then save as SVG.
You can open the .svg file in your code editor and you will see XML markup, including codes which you can copy into your HTML, like in #Miran's example:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" version="1.1" role="img" aria-hidden="true" focusable="false">
[copy the <path> elements here]
</svg>
Or save the .svg file somewhere and refer to it in your CSS:
/* Add calendar icon */
.wp-social-link.my-calendar-icon > a {
background-image: url(assets/images/my-calendar.svg);
background-repeat: no-repeat;
background-position: center;
background-size: 36px;
width: 54px;
height: 54px;
filter: invert(100%) brightness(100%) contrast(100%);
}

Infinity Symbol in CSS

I'm looking at creating a Infinity Symbol using CSS, SVG or Canvas.
If you don't know what an infinity symbol is, this is an example:
I have attempted at created the shape but have only managed to create one side of the shape. I would ultimately like to keep this to one element and as simple as possible.
.infinity {
width: 100px;
height: 100px;
border-radius: 50% 50% 0 50%;
border: 5px solid black;
transform: rotate(-45deg);
}
<div class="infinity"></div>
I have found this question:
Infinity symbol with HTML
But i'm looking at using this as an icon or image of some sort and therefore would like a bit more freedom with the shape.
CSS
By using pseudo-elements, you can create both sides of the shape and therefore get the output required.
This solution will be well supported across all browsers.
div {
position: relative;
width: 178px;
height: 100px;
}
div:before,
div:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 60px;
height: 60px;
border: 10px solid black;
border-radius: 50px 50px 0 50px;
transform: rotate(-45deg);
}
div:after {
left: auto;
right: 0;
border-radius: 50px 50px 50px 0;
transform: rotate(45deg);
}
<div></div>
This is an amended version from here: CSS-Tricks
If you want it more shapely, a bit of amending to the border radius rules really help give it some more shape.
div {
position: relative;
width: 178px;
height: 100px;
}
div:before,
div:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 60px;
height: 60px;
border: 10px solid black;
border-radius: 80% 0 55% 50% / 55% 0 80% 50%;
transform: rotate(45deg);
}
div:after {
left: auto;
right: 0;
transform: rotate(-135deg);
}
<div></div>
SVG
SVG stands for Scalable Vector Graphic. The web browser views it as an image but you can add text and normal HTML elements within an SVG.
It is well supported across all browsers as viewable here: CanIUse
SVG | MDN
<svg height="150" viewbox="0 50 200 200">
<path fill="none" stroke="#333333" stroke-width="5" d="M100,100
C200,0 200,200 100,100
C0,0 0,200 100,100z" />
</svg>
Canvas
Canvas is similar to SVG but uses a raster (pixel based) instead of a vector to create the shape.
The browser support for Canvas is quite good.
var shape = document.getElementById('infinity').getContext('2d');
shape.lineWidth = 6;
shape.strokeStyle = "#333";
shape.beginPath();
shape.moveTo(100, 100);
shape.bezierCurveTo(200, 0, 200, 200, 100, 100);
shape.bezierCurveTo(0, 0, 0, 200, 100, 100);
shape.closePath();
shape.stroke();
<canvas id="infinity"></canvas>
HTML
As taken from the answer's in the near duplicate, this is an accumulation of all the HTML alternatives.
I've only added this for canonical and to show to users that the shape is possible with HTML entities.
p {
font-size: 2em;
}
<p>∞</p>
<p>∞</p>
<p>∞</p>
<p>∞</p>

CSS - how to create circle pie canvas like this?

I really like this element,
but how to create it? I am not sure what's the correct designation of the element...
Thank you very much.
This effect can be achieved by layering a couple arc()s:
// bright blue full circle
d.beginPath();
d.arc(50, 50, 50, 0, 2 * Math.PI, false);
d.fillStyle = "#aaeeff";
d.fill();
// dark blue percentage circle
d.beginPath();
d.moveTo(50, 50);
d.arc(50, 50, 50, -0.5 * Math.PI, 0.78 * 2 * Math.PI - 0.5 * Math.PI, false);
d.fillStyle = "#00aaff";
d.fill();
// white inner filler
d.beginPath();
d.moveTo(50, 50);
d.arc(50, 50, 25, 0, 2 * Math.PI, false);
d.fillStyle = "#ffffff";
d.fill();
and finally rendering the text:
d.moveTo(50, 50);
d.fillStyle = "#606060";
d.font = "12pt sans-serif";
d.fillText("78%", 36, 56);
Fiddle: http://jsfiddle.net/j6NVg/
Instead of using the <canvas> element, I have chosen to construct the pie chart relying on CSS and JS entirely. The HTML markup is as follow:
<div class="pie" data-percent="78">
<div class="left">
<span></span>
</div>
<div class="right">
<span></span>
</div>
</div>
The CSS is as follow. The trick is to split the circle into two halves (the nested .left and .right elements). The halves will have their overflowing content hidden, and contain nested <span> that we will manipulate with JS for rotation later. Add vendor prefixes when appropriate :)
.pie {
background-color: #eee;
border-radius: 50%;
width: 200px;
height: 200px;
overflow: hidden;
position: relative;
}
.pie > div {
float: left;
width: 50%;
height: 100%;
position: relative;
overflow: hidden;
}
.pie span {
background-color: #4a7298;
display: block;
width: 100%;
height: 100%;
}
.pie .left span {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
-webkit-transform-origin: 100% 50%;
transform-origin: 100% 50%;
}
.pie .right span {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
-webkit-transform-origin: 0% 50%;
transform-origin: 0% 50%;
}
.pie:before,
.pie:after {
border-radius: 50%;
display: block;
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
}
.pie:before {
background-color: #fff;
content: "";
width: 75%;
height: 75%;
z-index: 100;
}
.pie:after {
content: attr(data-percent) "%";
z-index: 200;
text-align: center;
}
I have used the following with jQuery:
$(function() {
$(".pie").each(function() {
var percent = $(this).data("percent").slice(0,-1), // Removes '%'
$left = $(this).find(".left span"),
$right = $(this).find(".right span"),
deg;
if(percent<=50) {
// Hide left
$left.hide();
// Adjust right
deg = 180 - (percent/100*360)
$right.css({
"transform": "rotateZ(-"+deg+"deg)"
});
} else {
// Adjust left
deg = 180 - ((percent-50)/100*360)
$left.css({
"transform": "rotateZ(-"+deg+"deg)"
});
}
});
});
Here is the fiddle: http://jsfiddle.net/Aw5Rf/7/
Check the below links for more info (not an exact one.But you can get some idea).
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Canvas Test</title>
</head>
<body>
<section>
<div>
<canvas id="canvas" width="400" height="300">
This text is displayed if your browser does not support HTML5 Canvas.
</canvas>
</div>
<script type="text/javascript">
var myColor = ["#ECD078","#D95B43","#C02942","#542437","#53777A"];
var myData = [10,30,20,60,40];
function getTotal(){
var myTotal = 0;
for (var j = 0; j < myData.length; j++) {
myTotal += (typeof myData[j] == 'number') ? myData[j] : 0;
}
return myTotal;
}
function plotData() {
var canvas;
var ctx;
var lastend = 0;
var myTotal = getTotal();
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < myData.length; i++) {
ctx.fillStyle = myColor[i];
ctx.beginPath();
ctx.moveTo(200,150);
ctx.arc(200,150,150,lastend,lastend+
(Math.PI*2*(myData[i]/myTotal)),false);
ctx.lineTo(200,150);
ctx.fill();
lastend += Math.PI*2*(myData[i]/myTotal);
}
}
plotData();
</script>
</section>
</body>
</html>
For more info :Graphing Data in the HTML5 Canvas Element Simple Pie Charts
Another Link : Pure CSS3 Pie Charts effect
This is an online demo: http://jsbin.com/uFaSOwO/1/
First of all what you need can be done exactly using jQuery knob plugin. Still interested in a CSS Solution, than here's what I have done
<div class="load_me"></div>
.load_me {
margin: 100px;
height: 50px;
width: 50px;
border: 5px solid #f00;
border-radius: 50%;
border-top-color: transparent;
}
Demo
Animating the Knob Credits
If you want to prevent the mouse alteration, you can simply add readOnly
$this.knob({
readOnly: true
});
Demo
FIDDLE with ANIMATION
Here's my approach:
var ctx = canvas.getContext('2d');
/*
* in canvas, 0 degrees angle is on the right edge of a circle,
* while we want to start at the top edge of the circle.
* We'll use this variable to compensate the difference.
*/
var relativeAngle = 270;
function drawCanvas() {
ctx.clearRect(0, 0, 90, 90);
//light blue circle
ctx.lineWidth = 20;
ctx.strokeStyle = '#D8E8F7';
ctx.beginPath();
ctx.arc(45, 45, 35, 0, 2*Math.PI);
ctx.stroke();
//dark blue circle
ctx.strokeStyle = '#66ADF4';
ctx.beginPath();
//notice the angle conversion from degrees to radians in the 5th argument
ctx.arc(45, 45, 35, 1.5*Math.PI, ((angle + relativeAngle) / 180) * Math.PI);
ctx.stroke();
//text
ctx.textBaseline = 'middle';
ctx.textAlign = 'center';
ctx.fillStyle = '#666';
ctx.font = 'bold 14px serif';
// angle conversion to percentage value
ctx.fillText(parseInt(100 * angle / 360).toString() + '%', 45, 45);
}
var angle;
function timeout() {
angle = parseInt(360 * percent / 100);
drawCanvas();
if (angle > 360) {
document.getElementById('run').disabled = false;
percent = 0;
return;
}
percent++;
setTimeout(timeout, 10);
};
var percent = 0;
/* START the ANIMATION */
timeout();
At the bottom of the code you'll find a self evaluating function timeout which calls the drawCanvas function every 10 miliseconds and increments the blue circle angle. I hope everything is clear here. If not, feel free to ask!
Enjoy it!

CSS3: Calculate difference between (left + scale3d) and (transition3d + scale3d)

Why is there a difference between (scale3d and left) and (scale3d and translate3d)? And how do I calculate the difference between them?
See example: jsBin
div {
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 200px;
background: rgba(0,0,0, .3);
border-radius:7px;
font-size:20px;
-webkit-transform-origin:50% 50%;
}
#t1 {
left: 200px;
-webkit-transform: scale3d(0.5, 0.5, 1);
}
#t2 {
top: 200px;
-webkit-transform: scale3d(0.5, 0.5, 1) translate3d(200px, 0, 0);
}
and the simple HTML:
<div id="t1">scale3d and left</div>
<div id="t2">scale3d and transition3d</div>
CSS3 Transforms alter the local coordinate system. When you scale an element you're also scaling any translations applied to that div. Here - if you change the translate to 400px - you get the same result (reversing the effect of the scale).
You can check what transformations are currently applied to an element by using getComputedStyle().