How can I render country flags as a ribbon, using CSS only? - html

I need to present some data. Each block of data needs a country flag. I would like to display the country flag, using a nice little hanging banner, like this:
This image is edited in paint, and the example I've used, comes from this page
This link right here, shows how to display flags of Europe++ in pure CSS. In my system, I only need Nordic flags, which are all represented by a cross.
From the codepen example:
#function cross($back, $main, $detail: $back){
#return linear-gradient(90deg, transparent 28%, $main 28%, $main 34%, transparent 34%),
linear-gradient(transparent 42%, $detail 42%, $detail 46%, $main 46%, $main 58%, $detail 58%, $detail 62%, transparent 62%),
linear-gradient(90deg, $back 25%, $detail 25%, $detail 28%, $main 28%, $main 34%, $detail 34%, $detail 37%, $back 37%);
}
If I derive this (and rotate it 90deg to fit my preferred orientation, I can get something like this:
HTML:
<div class="norway"></div>
CSS:
.norway{
background: linear-gradient(180deg, transparent 28%, blue 28%, blue 34%, transparent 34%),
linear-gradient(90deg, transparent 42%, white 42%, white 46%, blue 46%,
blue 58%, white 58%, white 62%, transparent 62%),
linear-gradient(180deg, red 25%, white 25%, white 28%, blue 28%, blue 34%,
white 34%, white 37%, red 37%);
height: 600px;
width: 400px;
}
The hanging banner example however, is not really displaying the element itself, merely its border. I like the split in the bottom, So I would like to be able to set the linear gradients on the different border sides individually, or somehow otherwise solve the problem. I have tried a few approaches, but I can't seem to make the gradients work on individual border sides.
Does anyone know how I can display my flags as split end ribbons, using only CSS?
By the way, the Czech Republic is easy...
UPDATE:
I was able to render a Norwegian version, but I had to make two elements. One displaying the flag in the background of an element, and another element over it, displaying only the bottom border, in the same color as the block background. It seems like a pretty fragile solution, though...
https://jsfiddle.net/azjctc1y/

Note: After looking at Joseph's answer, I'd suggest you to go with that but this is another way.
Instead of using border to create the flag, we can use background with linear-gradient images like in the below snippet.
/* Latest compiled and minified CSS included as External Resource*/
html {
margin: 20px;
}
/* Optional theme */
#import url('//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-theme.min.css');
body {
margin: 10px;
}
.test-container {
background-color: lightgrey;
border: 1px solid black;
position: relative;
padding: 10px;
margin: 10px;
min-height: 100px;
}
.close-ribbon {
position: absolute;
top: 0;
right: 1em;
z-index: 1;
color: #eee;
font-size: 2em;
}
.close-ribbon:before {
content: "";
font-size: 0.5em;
position: absolute;
border-style: solid;
border-color: transparent transparent #B71C1C transparent;
top: -1em;
right: 3em;
border-width: 0 0 1em 0.7em;
z-index: -1;
}
.close-ribbon:after {
position: absolute;
content: "";
top: -1em;
right: 0;
height: 5em;
width: 3em;
background: linear-gradient(to bottom right, transparent 48%, lightgrey 52%), linear-gradient(to bottom left, transparent 48%, lightgrey 52%), linear-gradient(180deg, transparent 38%, blue 38%, blue 44%, transparent 44%), linear-gradient(90deg, transparent 40%, white 40%, white 46%, blue 46%, blue 56%, white 55%, white 62%, transparent 62%), linear-gradient(180deg, red 35%, white 35%, white 38%, blue 38%, blue 44%, white 44%, white 47%, red 47%), linear-gradient(to bottom right, red 50%, lightgrey 55%), linear-gradient(to top right, lightgrey 45%, red 50%);
background-size: 1.6em 1.4em, 1.45em 1.4em, 3em 4em, 3em 4em, 3em 4em, 1.2em 1.1em, 1.2em 1.1em;
background-position: 0% 100%, 100% 100%, 0% 0%, 0% 0%, 0% 0%, 0% 100%, 100% 100%;
background-repeat: no-repeat;
font-size: 0.5em;
z-index: -1;
-webkit-transition: height 0.5s;
transition: height 0.5s;
}
<div class="container">
<div class="row">
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
<div class="test-container">
<a class="close-ribbon"></a>
Czech Republic is easy...
</div>
</div>
</div>
</div>
Original Answer:
It is not 100% like the image provided in question or the ouput of your fiddle because the blue cross doesn't have the small triangular cut because I was trying create a cut that was transparent (so that you can use it on top of an element with any background). But if it is always going to be a grey background then that can also be done.
The below is the code that I have added:
.close-ribbon:after {
position: absolute;
content: "";
top: -1em;
right: 0;
height: 5em;
width: 3em;
background: linear-gradient(180deg, transparent 28%, blue 28%, blue 34%, transparent 34%), linear-gradient(90deg, transparent 40%, white 40%, white 46%, blue 46%, blue 58%, white 58%, white 62%, transparent 62%), linear-gradient(180deg, red 25%, white 25%, white 28%, blue 28%, blue 34%, white 34%, white 37%, red 37%), linear-gradient(to bottom right, red 50%, transparent 55%), linear-gradient(to top right, transparent 45%, red 50%);
background-size: 3em 4em, 3em 4em, 3em 4em, 1.25em 1em, 1.2em 1em;
background-position: 0% 0%, 0% 0%, 0% 0%, 0% 100%, 100% 100%;
background-repeat: no-repeat;
/* other styles */
}
/* Latest compiled and minified CSS included as External Resource*/
/* Optional theme */
#import url('//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-theme.min.css');
body {
margin: 10px;
}
.test-container {
background-color: lightgrey;
border: 1px solid black;
position: relative;
padding: 10px;
margin: 10px;
min-height: 100px;
}
.close-ribbon {
position: absolute;
top: 0;
right: 1em;
z-index: 1;
color: #eee;
font-size: 2em;
}
.close-ribbon:before {
content: "";
font-size: 0.5em;
position: absolute;
border-style: solid;
border-color: transparent transparent #B71C1C transparent;
top: -1em;
right: 3em;
border-width: 0 0 1em 0.7em;
z-index: -1;
}
.close-ribbon:after {
position: absolute;
content: "";
top: -1em;
right: 0;
height: 5em;
width: 3em;
background: linear-gradient(180deg, transparent 28%, blue 28%, blue 34%, transparent 34%), linear-gradient(90deg, transparent 40%, white 40%, white 46%, blue 46%, blue 58%, white 58%, white 62%, transparent 62%), linear-gradient(180deg, red 25%, white 25%, white 28%, blue 28%, blue 34%, white 34%, white 37%, red 37%), linear-gradient(to bottom right, red 50%, transparent 55%), linear-gradient(to top right, transparent 45%, red 50%);
background-size: 3em 4em, 3em 4em, 3em 4em, 1.2em 1em, 1.2em 1em;
background-position: 0% 0%, 0% 0%, 0% 0%, 0% 100%, 100% 100%;
background-repeat: no-repeat;
font-size: 0.5em;
z-index: -1;
-webkit-transition: height 0.5s;
transition: height 0.5s;
}
<div class="container">
<div class="row">
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
<div class="test-container">
<a class="close-ribbon"></a>
Czech Republic is easy...
</div>
</div>
</div>
</div>

You have a great base to go on. It just needs a few tweaks here and there. (Making individual styles for flags is going to be a colossal pain though). There's just a few places you could improve it. In most cases when using absolute positioning, you may want to have whatever you are positioning align with some edge of the parent element. For that you can use negative values like left: -1em or whatever, but a lot of times, it's more robust to leave left auto and set the right attribute to 100%. You also set the bottom border to right:0. In throwing it in this answer I discovered that the font size difference caused it to be aligned incorrectly. One way you can fix that is to give it a left:50% with a negative margin equal to the left border. In this case it's 1.5em. A few changes, but it's all about understanding and leveraging top, right, bottom, and left to their fullest potential, which includes percent based values.
Hope it helps!
body {
padding: 2em;
}
/* Latest compiled and minified CSS included as External Resource*/
/* Optional theme */
#import url('//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap-theme.min.css');
body {
margin: 10px;
}
.test-container{
background-color: lightgrey;
border: 1px solid black;
position: relative;
padding: 10px;
margin: 10px;
min-height: 100px;
}
.ribbon {
position: absolute;
top: 0;
right: 1em;
z-index: 1;
color: #eee;
font-size: 2em;
}
.norway {
position: absolute;
top: -0.5em;
right: 1em;
z-index: 1;
font-size: 2em;
height: 70px;
width: 42px;
background: linear-gradient(180deg, transparent 28%, blue 28%, blue 34%, transparent 34%),
linear-gradient(90deg, transparent 40%, white 40%, white 46%, blue 46%, blue 54%, white 54%, white 60%, transparent 60%),
linear-gradient(180deg, red 25%, white 25%, white 28%, blue 28%, blue 34%, white 34%, white 37%, red 37%);
}
.ribbon:before {
content: "";
font-size: 0.5em;
position: absolute;
border-style: solid;
border-color: transparent transparent #B71C1C transparent;
top: 0;
right: 100%;
border-width: 0 0 1em 0.7em;
z-index: -1;
}
.ribbon:after {
content: "";
font-size: 0.5em;
position: absolute;
height: 5em;
border: 1.5em solid #F44336;
z-index: -1;
bottom: 0;
border-top-width: 1.5em;
border-bottom-color: lightgrey;
border-right-color: transparent;
border-left-color: transparent;
border-top-color: transparent;
left: 50%;
margin-left: -1.5em;
-webkit-transition: height 0.5s;
transition: height 0.5s;
}
<div class="container">
<div class="row">
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12">
<div class="test-container">
<a class="norway ribbon"></a>
Norway
</div>
</div>
</div>
</div>

Inserted a div into the anchor tag and styled a before and after content to display the blue cross. Used a + symbol to display the white underneath cross.
jsfiddle.net/8g1w5va9/4
EDIT
Just saw your fiddle. Looks good! Was just going to suggest something like that but decided to at least build somewhat of a working model.

Related

How can I combine a circle in a polygon using clip-path and add a shadow

I am new to using the css property clip-path and have created a shape that almost fits the requirement I have.
I am looking to create the following shape however struggling to convert the squares I have to circles.
.ticket {
background-color: blue;
height: 100px;
width: 200px;
border-radius: 10px;
box-shadow: 0 0.5rem 1rem rgb(0 0 0 / 15%);
clip-path: polygon(
0 0,
0% 42%,
5% 42%,
5% 58%,
0 58%,
0 100%,
100% 100%,
100% 58%,
95% 58%,
95% 42%,
100% 42%,
100% 0
);
}
<div class="ticket"></div>
Is this possible using this property? If not, how could I achieve this using a SVG instead? Is it also possible to add a drop shadow to this clipped mask? As you can see in the snippet the shadow doesn't really work.
If it's only a solid coloration, background can do it:
.ticket {
background:
radial-gradient(20px at right, #0000 97%,blue) right,
radial-gradient(20px at left , #0000 97%,blue) left;
background-size: 51% 100%;
background-repeat: no-repeat;
height: 100px;
width: 200px;
border-radius: 10px;
filter: drop-shadow(0 0.5rem 0.2rem rgb(0 0 0 / 50%));
}
<div class="ticket"></div>
It is possible to 'cut holes' using the mask-image property and radial-gradients.
This snippet uses your code but replacing the clip-path with circle radial-gradient masks. Obviously you can change the percentages depending on hole-size required.
body {
background: cyan;
}
.ticket {
background-color: blue;
height: 100px;
width: 200px;
border-radius: 10px;
box-shadow: 0 0.5rem 1rem rgb(0 0 0 / 15%);
--mask1: radial-gradient(circle at 0 50%, transparent 0, transparent 5%, black 5%, black 90%, transparent 90%, transparent);
--mask2: radial-gradient(circle at 100% 50%, transparent 0, transparent 5%, black 5%, black 90%, transparent 90%, transparent);
/* webkit needed for Chrome */
-webkit-mask-image: var(--mask1), var(--mask2);
mask-image: var(--mask1), var(--mask2);
}
<div class="ticket"></div>
(body has been given a background just to prove that holes have been cut rather than white circles drawn which is what would have happened with pseudo elements).
The box shadow is more problematic as it gets masked (or clipped as in the question's code). Box-shadow on element with -webkit-mask-image has ideas on putting a shadow on a containing element which has the mask image(s) as background images(s) but putting a shadow into the holes is still a problem. Perhaps just putting a slightly bigger container with gradient gray/transparent backgrounds would do enough, with the 'holes' varying transparent grays rather than just transparent. Seems hacky though.
Here is my solution for both contained and outlined coupons with mask-image and radial-gradient .
In order to draw an outlined coupon, I use two backgrounds and masks, each of which is only a half part to avoid overlapping of radial-gradient.
.wrapper {
display: flex;
gap: 30px;
--coupon-side-radius: 6px;
--coupon-background-color: #c39f76;
--coupon-border-color: #c39f76;
--coupon-border-width: 1px;
}
.coupon {
width: 100px;
height: 100px;
border: var(--coupon-border-width, 1px) solid var(--coupon-border-color);
border-radius: 6px;
box-sizing: border-box;
background: radial-gradient(
circle at center left,
transparent 0px var(--coupon-side-radius),
var(--coupon-border-color) var(--coupon-side-radius)
calc(var(--coupon-side-radius) + var(--coupon-border-width, 0.5px)),
var(--coupon-background-color) calc(var(--coupon-side-radius) + var(--coupon-border-width) + 0.5px)
)
border-box,
radial-gradient(
circle at center right,
transparent 0px var(--coupon-side-radius),
var(--coupon-border-color) var(--coupon-side-radius)
calc(var(--coupon-side-radius) + var(--coupon-border-width, 0.5px)),
var(--coupon-background-color) calc(var(--coupon-side-radius) + var(--coupon-border-width, 0.5px) + 0.5px)
)
border-box;
background-size: 50% 100%, 50% 100%;
background-position: 0% 100%, 100% 100%;
background-repeat: no-repeat, no-repeat;
-webkit-mask-image: radial-gradient(
circle at center left,
transparent 0,
transparent var(--coupon-side-radius),
#000 calc(var(--coupon-side-radius) + 0.5px)
),
radial-gradient(
circle at center right,
transparent 0,
transparent var(--coupon-side-radius),
#000 calc(var(--coupon-side-radius) + 0.5px)
);
-webkit-mask-size: 50% 100%, 50% 100%;
-webkit-mask-position: 0% 100%, 100% 100%;
-webkit-mask-repeat: no-repeat, no-repeat;
}
.coupon1 {
--coupon-side-radius: 6px;
--coupon-background-color: #c39f76;
--coupon-border-color: #c39f76;
--coupon-border-width: 1px;
}
.coupon2 {
--coupon-side-radius: 6px;
--coupon-border-color: red;
--coupon-border-width: 1px;
--coupon-background-color: #c39f76;
}
.coupon3 {
--coupon-side-radius: 6px;
--coupon-background-color: transparent;
--coupon-border-color: red;
--coupon-border-width: 1px;
}
.coupon4 {
--coupon-side-radius: 6px;
--coupon-background-color: transparent;
--coupon-border-color: red;
--coupon-border-width: 2px;
}
.coupon5 {
--coupon-side-radius: 6px;
--coupon-background-color: transparent;
--coupon-border-color: red;
--coupon-border-width: 0.5px;
border: none !important;
position: relative;
}
.coupon5::before{
content: "";
position: absolute;
top: 0px;
left: 0px;
box-sizing: border-box;
width: 200%;
height: 200%;
transform: scale(0.5);
transform-origin: left top;
border: 1px solid red;
border-radius: 16px;
opacity: 0.7;
}
.coupon-demo {
width: 100px;
height: 100px;
border: 2px solid red;
border-radius: 15px;
background: radial-gradient(
circle at center left,
transparent 0px 6px,
red 6px 8px,
#fff 9px
)
border-box,
radial-gradient(
circle at center right,
transparent 0px 6px,
red 6px 8px,
#c39f76 9px
)
border-box;
background-size: 51% 100%, 50% 100%;
background-position: 0% 100%, 100% 100%;
background-repeat: no-repeat, no-repeat;
-webkit-mask-image: radial-gradient(
circle at center left,
transparent 0,
transparent 6px,
red 7px
),
radial-gradient(
circle at center right,
transparent 0,
transparent 6px,
red 7px
);
-webkit-mask-size: 50% 100%, 50% 100%;
-webkit-mask-position: 0% 100%, 100% 100%;
-webkit-mask-repeat: no-repeat, no-repeat;
}
<div class="wrapper">
<div class="coupon coupon1">1. Contained</div>
<div class="coupon coupon2">2. Contained + Outlined</div>
<div class="coupon coupon3">3. Outlined</div>
<div class="coupon coupon4">4. Border 2px</div>
<div class="coupon coupon5">5. Border 0.5px </div>
<div class="coupon-demo">6. For debug purpose </div>
<div>

Can you have background-image: linear-gradient( to center...);

I have a div with background-image: linear-gradient( to bottom, red, blue);
but I want the to bottom to be to center but it does not work.
wright, now it looks like this
I want it to look like this
Does anyone know how to do this pleas help me?
What you are showing is a classic border:
.box {
border:40px solid blue;
height:50px;
width:50px;
background:red;
}
<div class="box"></div>
But I suspect you want a color fading so what you want is a radial-gradient
.box {
height:200px;
width:200px;
background:radial-gradient(farthest-side,red,blue);
}
<div class="box"></div>
Or maybe like below:
.box {
height: 200px;
width: 200px;
background: linear-gradient(to right, blue, red, blue);
position: relative;
}
.box::before {
content: "";
display: block;
height: 100%;
background: linear-gradient(blue, red, blue);
clip-path: polygon(0 0, 100% 100%, 0 100%, 100% 0);
}
<div class="box"></div>
Or like this:
.box {
height: 200px;
width: 200px;
background:
linear-gradient(to top right , red, blue) top right,
linear-gradient(to top left , red, blue) top left ,
linear-gradient(to bottom left , red, blue) bottom left,
linear-gradient(to bottom right, red, blue) bottom right;
background-size:50% 50%;
background-repeat:no-repeat;
}
<div class="box"></div>
Also using box-shadow
.box {
height: 200px;
width: 200px;
background: red;
box-shadow: 0 0 50px 35px blue inset;
}
<div class="box"></div>
What you can do is to utilize multiple background gradients:
.item {
--outerColor: blue;
--innerColor: red;
width: 120px;
height: 120px;
background-color: var(--innerColor);
background-image: linear-gradient(to bottom, var(--outerColor) 25%, transparent 25%, transparent 75%, var(--outerColor) 75%), linear-gradient(to right, var(--outerColor) 25%, transparent 25%, transparent 75%, var(--outerColor) 75%);
}
<div class="item"></div>
Here's how it works:
Step 1: Make pure red background:
.item {
--innerColor: red;
width: 120px;
height: 120px;
background-color: var(--innerColor);
}
<div class="item"></div>
Step 2: Add horizontal stripe
.item {
--outerColor: blue;
--innerColor: red;
width: 120px;
height: 120px;
background-color: var(--innerColor);
background-image: linear-gradient(to bottom, var(--outerColor) 25%, transparent 25%, transparent 75%, var(--outerColor) 75%);
}
<div class="item"></div>
Step 3: Add vertical stripe
.item {
--outerColor: blue;
--innerColor: red;
width: 120px;
height: 120px;
background-color: var(--innerColor);
background-image: linear-gradient(to bottom, var(--outerColor) 25%, transparent 25%, transparent 75%, var(--outerColor) 75%), linear-gradient(to right, var(--outerColor) 25%, transparent 25%, transparent 75%, var(--outerColor) 75%);
}
<div class="item"></div>
I think you want like this.
#grad1 {
height: 200px;
width: 200px;
background:
linear-gradient(90deg, blue, rgba(0,255,0,0) 30%),
linear-gradient(180deg, blue, rgba(0,0,255,0) 30%),
linear-gradient(0deg, blue, rgba(0,255,0,0) 30%),
linear-gradient(270deg, blue, rgba(0,0,255,0) 30%),
linear-gradient(0deg, blue, red, red 50%),
linear-gradient(90deg, blue, red, red 50%),
linear-gradient(180deg, blue, red, red 50%),
linear-gradient(270deg, blue, red, red 50%);
}
<div id="grad1"></div>

How to make a border around clip path shape? [duplicate]

This question already has answers here:
Hexagon shape with a border/outline
(7 answers)
Closed 3 years ago.
I am trying to create hexagon shaped buttons that have a transparent background and white 1px solid border around the hexagon I created with clip path. However, when I apply a border part of it is cut off. How can I achieve this look?
Here is my code:
.project-button div{
position: relative;
display: inline-block;
padding: 1rem;
margin: 0 1rem 1rem 1rem;
color: #d9d9d9;
font-size: 1rem;
font-weight: 700;
border: 1px solid white;
-webkit-clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
background-repeat: no-repeat;
transition: background-size .5s, color .5s;
}
.to-top {
background-position: 50% 100%;
background-size: 100% 0%;
}
.project-button div:hover {
background-size: 100% 100%;
background-image: linear-gradient(white, white);
color: #51d0de;
}
<div class="project-button">
<div class="to-top>View Code"></div>
</div>
This is what i Got so far,
I've used filter: drop-shadow()
For your transparent background you can use same color as parent
.hexagon{
background: white;/*giving color is important*/
padding: 40px;
width: 20%;
text-align: center;
clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
}
/* main code */
.container{
filter: drop-shadow(0px 0px 1px black);
}
<div class="container">
<div class="hexagon">Button</div>
</div>
I hope it helps.
Note: filter is used on parent div.

Overflow visible on text input, is it possible?

CSS overflow:visible doesn't seem to get applied to inputs.
See the following JS fiddle: https://jsfiddle.net/b4sr578j/
input {
border: 1px dashed black;
overflow: visible;
height: 28px;
font-size: 30px;
}
<input type='text' value='gggyyyXXX'/>
Is it possible to make the bottom of the gs and ys visible (without increasing the height of the text input)?
Thanks for any help.
Answer to the original question - As indicated already by Sebastian Hens, this is not possible. The reason is because input elements are replaced elements and the overflow property applies only to non-replaced elements.
Quote from MDN about overflow property:
Applies to - non-replaced block-level elements and non-replaced inline-block elements
As already mentioned in comments, the ideal solution would be to make use of contenteditable elements because they do respect the overflow settings.
Here is a workaround solution which uses multiple linear-gradient to generate the dashed border effect. Part of the answer is adopted from Danield's answer (the parts about padding and removal of height). On top of it, I have modified the appearance and added the gradients.
Though we haven't added the height explicitly, the actual height of the area within the border would still be the same as that in your original code. I have added an input box with your original code on the left side for comparison. I don't know if that is acceptable for you. If you mandatorily want the height to be set then this would not work.
input.test {
appearance: none;
box-sizing: border-box;
font-size: 30px;
padding: 2px 0px 6px;
border: 0;
background: linear-gradient(to right, gray 50%, transparent 50%), linear-gradient(to right, gray 50%, transparent 50%), linear-gradient(to bottom, gray 50%, transparent 50%), linear-gradient(to bottom, gray 50%, transparent 50%);
background-size: 8px 1px, 8px 1px, 1px 8px, 1px 8px;
background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
background-position: 0px 0px, 0px 1em, 0px 0px, 100% 0px;
box-shadow: inset 0px -10px 0px white;
width: 200px;
}
input.original {
border: 1px dashed black;
overflow: visible;
height: 28px;
font-size: 30px;
width: 200px;
}
input{
vertical-align: top;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<input type='text' value='gggyyyXXX' class='original' />
<input type='text' value='gggyyyXXX' class='test' />
In the above snippet a white box-shadow is used to hide the bottom part of the gradient so that it doesn't overflow (you can see the effect by removing the box-shadow) and because of this it needs a solid color background. On the other hand if the height of your text box is fixed then you could use something like the below snippet to even support non solid backgrounds.
input.original {
border: 1px dashed black;
overflow: visible;
height: 28px;
font-size: 30px;
width: 200px;
}
input.test-fixedheight {
appearance: none;
box-sizing: border-box;
font-size: 30px;
padding: 2px 0px 6px;
border: 0;
background: linear-gradient(to right, crimson 50%, transparent 50%), linear-gradient(to right, crimson 50%, transparent 50%), linear-gradient(to bottom, crimson 12.5%, transparent 12.5%, transparent 25%, crimson 25%, crimson 37.5%, transparent 37.5%, transparent 50%, crimson 50%, crimson 62.5%, transparent 62.5%, transparent 75%, crimson 75%, crimson 87.5%, transparent 87.5%), linear-gradient(to bottom, crimson 12.5%, transparent 12.5%, transparent 25%, crimson 25%, crimson 37.5%, transparent 37.5%, transparent 50%, crimson 50%, crimson 62.5%, transparent 62.5%, transparent 75%, crimson 75%, crimson 87.5%, transparent 87.5%),linear-gradient(to bottom, transparent 0%, white 0%);
background-size: 8px 1px, 8px 1px, 1px 1em, 1px 1em, 100% 1em;
background-repeat: repeat-x, repeat-x, no-repeat, no-repeat;
background-position: 0px 0px, 0px 29px, 0px 2px, 100% 2px;
width: 200px;
}
input.test-fixedheight-transparent {
appearance: none;
box-sizing: border-box;
font-size: 30px;
padding: 2px 0px 6px;
border: 0;
background: linear-gradient(to right, beige 50%, transparent 50%), linear-gradient(to right, beige 50%, transparent 50%), linear-gradient(to bottom, beige 12.5%, transparent 12.5%, transparent 25%, beige 25%, beige 37.5%, transparent 37.5%, transparent 50%, crimson 50%, beige 62.5%, transparent 62.5%, transparent 75%, beige 75%, beige 87.5%, transparent 87.5%), linear-gradient(to bottom, beige 12.5%, transparent 12.5%, transparent 25%, beige 25%, beige 37.5%, transparent 37.5%, transparent 50%, beige 50%, beige 62.5%, transparent 62.5%, transparent 75%, beige 75%, beige 87.5%, transparent 87.5%);
background-size: 8px 1px, 8px 1px, 1px 1em, 1px 1em;
background-repeat: repeat-x, repeat-x, no-repeat, no-repeat;
background-position: 0px 0px, 0px 29px, 0px 2px, 100% 2px;
width: 200px;
}
/* Just for demo */
body{
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
input{
vertical-align: top;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<input type='text' value='gggyyyXXX' class='original' />
<input type='text' value='gggyyyXXX' class='test-fixedheight' />
<input type='text' value='gggyyyXXX' class='test-fixedheight-transparent' />
This approach is tested in Chrome, Firefox, Opera and IE11. Because gradients is supported in IE10, it should work fine there also but would not work with any of the lower versions as they don't support gradients.
Here's a solution for Webkit and Firefox:
(This won't work in IE - because it doesn't support outline-offset)
1) Remove the height
2) Use outline instead of border
3) Add a negative outline-offset
4) Add padding to fine tune the offset
FIDDLE
input {
overflow: visible;
font-size: 30px;
outline: 1px dashed black;
border: 0;
outline-offset: -8px;
padding: 6px 0 2px 8px;
}
<input type='text' value='gggyyyXXX' />
To make it short: No this is not possible!
The only thing what you could do is to create a javascript/html/css replacement for an input. But this would be an overhead.
To get an idea:
set the input to visibility hidden
position a DIV with the "input styling" under the input
let a javascript check if the user does a keypress while focusing the input an copy the input value to the div
More of a workaround really, but why not absolutely position an input with no border over the top?
body {
position:relative;
}
input {
border: 1px dashed black;
overflow: visible;
height: 28px;
font-size: 30px;
}
input.noborder {
border:1px transparent solid;
height:34px;
position:absolute;
left:0;
background:transparent;
}
<input type='text' value=''/>
<input class="noborder" type='text' value='gggyyyXXX'/>
Solution 1
Use Contenteditable
const editorElement = document.getElementById("editor");
editorElement.addEventListener("input", function(event) {
console.log("value: ", editorElement.innerText );
}, false);
<div contenteditable="true" id="editor">Please type something in here</div>
Solution 2
Use negative Margins on top and Bottom To prevent the text from overflowing the input:
input {
display: block;
margin-top: -5px;
margin-bottom: -25px;
height: 30px;
}
<div>Content before</div>
<input type="text" value="input Value"/><br>
<div>Content after</div>
i doubt it can be done like this. input uses size attribute for this. so manipulate size, using code. for eg. in php;
<input type="text" name="nm" size = "<?php if(strlen($text)<=10)echo 10;
else echo strlen($text); ?>" >

How to achieve chamfered CSS Border Corners rather than rounded corners?

With the CSS border-radius property I can have a curvy, rounded border corner at the end.
.boxLeft{
border-right: 1px dashed #333;
border-bottom: 1px dashed #333;
border-radius: 0 0 10px 0;
}
.boxRight{
border-left: 1px dashed #333;
border-bottom: 1px dashed #333;
border-radius: 0 0 0 10px;
}
But I want a border corner like the image below. If I have two boxes (Yellow & Pink) meeting each other and I want a harsh corner at the bottom meeting point (dotted corner), what should I do?
Is that possible using CSS?
CSS3 Gradients can do the trick:
Try this, Here's a Fiddle.
div {
background: #c00;
/* fallback */
background: -moz-linear-gradient(45deg, transparent 10px, #c00 10px), -moz-linear-gradient(135deg, transparent 10px, #c00 10px), -moz-linear-gradient(225deg, transparent 10px, #c00 10px), -moz-linear-gradient(315deg, transparent 10px, #c00 10px);
background: -o-linear-gradient(45deg, transparent 10px, #c00 10px), -o-linear-gradient(135deg, transparent 10px, #c00 10px), -o-linear-gradient(225deg, transparent 10px, #c00 10px), -o-linear-gradient(315deg, transparent 10px, #c00 10px);
background: -webkit-linear-gradient(45deg, transparent 10px, #c00 10px), -webkit-linear-gradient(135deg, transparent 10px, #c00 10px), -webkit-linear-gradient(225deg, transparent 10px, #c00 10px), -webkit-linear-gradient(315deg, transparent 10px, #c00 10px);
}
div {
background-position: bottom left, bottom right, top right, top left;
-moz-background-size: 50% 50%;
-webkit-background-size: 50% 50%;
background-size: 50% 50%;
background-repeat: no-repeat;
}
/* Ignore the CSS from this point, it's just to make the demo more presentable */
div {
float: left;
width: 50px;
margin: 15px auto;
padding: 15px;
color: white;
line-height: 1.5;
}
<div>Div 1</div>
<div>Div 2</div>
Here's a way, although it does have some shortcomings, like no borders and it isn't transparent:
.left,
.right {
width: 100px;
height: 100px;
float: left;
position: relative;
}
.left {
background: lightpink;
}
.right {
background: lightblue;
}
.right::after,
.left::after {
width: 0px;
height: 0px;
background: #fff;
content: '';
position: absolute;
bottom: 0;
}
.right::after {
left: 0;
border-top: 10px solid lightblue;
border-right: 10px solid lightblue;
border-left: 10px solid white;
border-bottom: 10px solid white;
}
.left::after {
right: 0;
border-top: 10px solid lightpink;
border-right: 10px solid white;
border-left: 10px solid lightpink;
border-bottom: 10px solid white;
}
<div class="left"></div>
<div class="right"></div>
RESULT:
Here's a fiddle.
This is also possible using "clip-path".
-webkit-clip-path: polygon(20% 0%, 80% 0%, 100% 20%, 100% 80%, 80% 100%, 20% 100%, 0% 80%, 0% 20%);
clip-path: polygon(20% 0%, 80% 0%, 100% 20%, 100% 80%, 80% 100%, 20% 100%, 0% 80%, 0% 20%);
div {
width: 200px;
height: 200px;
background: red;
-webkit-clip-path: polygon(20% 0%, 80% 0%, 100% 20%, 100% 80%, 80% 100%, 20% 100%, 0% 80%, 0% 20%);
clip-path: polygon(20% 0%, 80% 0%, 100% 20%, 100% 80%, 80% 100%, 20% 100%, 0% 80%, 0% 20%);
}
<div></div>
Source Codepen
Support for clip-path can be found here... http://caniuse.com/#search=clip-path
I first tested #thordarson solution with position: 'absolute'.
position: 'absolute',
top: '2.9rem',
left: '2.6rem',
borderLeft: '1rem solid #6CAEC6',
borderBottom: '0.7rem solid white',
This worked fine on most devices as shown in the first picture but when used on iPhones or tablets weird lines started showing up:
As #Collins answer I then started using clip-path: polygon but I had quite a hard time getting the correct shapes. I then found a site that really helped me:
https://bennettfeely.com/clippy/
They offer ready shapes that can then be dragged to a desired shape.
For the corner that I needed I could then copy the correct values from the website.
A requirement for us was a 35° angle and to get that right I used the site:
https://www.ginifab.com/feeds/angle_measurement/
I have no affiliation with any of the sites, they just really helped me get what I wanted. With clip-path: polygon and -webkit-clip-path: polygon it worked on all devices and browsers that we had as a requirement.
Compatibility check:
https://caniuse.com/#feat=css-clip-path
This is what you need, transparency and everything
.left,
.right {
width: 100px;
height: 100px;
float: left;
position: relative;
overflow: hidden;
}
.right::after,
.left::after {
content: '';
width: 200px;
height: 200px;
position: absolute;
-moz-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
-o-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.right::after {
background: lightblue;
left: -40px;
top: -100px;
}
.left::after {
background: lightpink;
left: -60px;
top: -100px;
}
<div class="left"></div>
<div class="right"></div>
A good The best way to archive this: border-images. In combination with .svg a good solution...
++ Includes Westworld Style UI in CSS ++
I've updated AlphaMale's awesome answer to hack chamfered borders as originally requested. It basically uses one chamfered div with a slightly smaller on inside it. The outer div's background colour becomes the border colour when the rest of it is covered up by the inner div with matching chamfers.
Tested in Edge, Chrome and Firefox.
I found this page while looking to duplicate something like the Westworld User Interface which has unequal chamfered corners. See the JS fiddle for how I've cobbled this together along with a colour scheme and example box from the Westworld speech chaining scene.
Code on JSFiddle (CSS below): http://jsfiddle.net/S2nqK/345/
Westworld UI pic at: https://qph.ec.quoracdn.net/main-qimg-44c9f03b2abfe9f3833763eece1b0cc4?convert_to_webp=true
body {background-color: #353535;
font-family: 'Open Sans';}
.div-outer {
/* Chrome / Safari */
background:
-webkit-linear-gradient(45deg, transparent 0px, #6ea1a1 0px), /* bottom left */
-webkit-linear-gradient(135deg, transparent 14px, #6ea1a1 14px), /* bottom right */
-webkit-linear-gradient(225deg, transparent 0px, #6ea1a1 0px), /* top right */
-webkit-linear-gradient(315deg, transparent 5px, #6ea1a1 5px); /* top left */
/* Firefox */
background:
-moz-linear-gradient(45deg, transparent 0px, #6ea1a1 0px), /* bottom left */
-moz-linear-gradient(135deg, transparent 14px, #6ea1a1 14px), /* bottom right */
-moz-linear-gradient(225deg, transparent 0px, #6ea1a1 0px), /* top right */
-moz-linear-gradient(315deg, transparent 5px, #6ea1a1 5px); /* top left */
/* Opera */
background:
-o-linear-gradient(45deg, transparent 0px, #6ea1a1 0px), /* bottom left */
-o-linear-gradient(135deg, transparent 14px, #6ea1a1 14px), /* bottom right */
-o-linear-gradient(225deg, transparent 0px, #6ea1a1 0px), /* top right */
-o-linear-gradient(315deg, transparent 5px, #6ea1a1 5px); /* top left */
padding: 2px;
color: #fff;
}
.div-inner {
background:
-webkit-linear-gradient(45deg, transparent 0px, #000 0px),
-webkit-linear-gradient(135deg, transparent 14px, #000 14px),
-webkit-linear-gradient(225deg, transparent 0px, #000 0px),
-webkit-linear-gradient(315deg, transparent 5px, #000 5px);
background:
-moz-linear-gradient(45deg, transparent 0px, #000 0px),
-moz-linear-gradient(135deg, transparent 14px, #000 14px),
-moz-linear-gradient(225deg, transparent 0px, #000 0px),
-moz-linear-gradient(315deg, transparent 5px, #000 5px);
background:
-o-linear-gradient(45deg, transparent 0px, #000 0px),
-o-linear-gradient(135deg, transparent 14px, #000 14px),
-o-linear-gradient(225deg, transparent 0px, #000 0px),
-o-linear-gradient(315deg, transparent 5px, #000 5px);
padding: 10px;
height: 92px;
text-align: center;
}
.div-outer, .div-inner {
background-position: bottom left, bottom right, top right, top left;
-moz-background-size: 50% 50%;
-webkit-background-size: 50% 50%;
background-size: 50% 50%;
background-repeat: no-repeat;
}
.contain {
width: 180px;
}
.title {background-color: #76ffff;
padding: 6px;
color: #000;
border-radius: 2px;
font-weight: bold;
text-align-last: justify;
text-align: justify;
}
.font-large {font-size: 34pt;}
.font-tiny {font-size: 10pt;}
.cyan {color: #76ffff;}
/* Ignore the CSS from this point, it's just to make the demo more presentable */
.arrow-right {
width: 0;
height: 0;
border-top: 8px solid transparent;
border-bottom: 8px solid transparent;
border-left: 8px solid #fff;
display: inline-block;
vertical-align: middle;
}
p:first-of-type { margin-top: 0 }
p:last-of-type { margin-bottom: 0}
Ok, so I made a JS library to automate creating chamfered borders.
It has two methods for creating the chamfers:
Method 1: it creates a chamfered background using Canvas API and set it as the CSS background-image of the element.
Method 2: it appends 4 CSS based triangle DOM elements around the target, making the chamfer.
You will stick with method 1 when you can let the library set the background-image, and you will need method 2 when your target already has a background, like in <img>'s.
The usage is simple, just call ChamferBg for using method 1, or ChamferEnvelop to use method 2:
var el = document.getElementById('box');
ChamferBg(el, {
size: 20,
sw: 6,
sc: '#447aec',
fc: '#21ceff',
tl: false,
br: false,
resize_observe: true
});
The options and their defaults are:
{
size: 5, // chamfer size
sw: 1, // stroke width
sc: 'black', // stroke color,
fc: undefined, // fill color
fp: undefined, // URL of an image to use as fill pattern
tl: true, // chamfer top-left corner?
tr: true, // chamfer top-right corner?
bl: true, // chamfer bottom-left corner?
br: true, // chamfer bottom-right corner?
resize_observe: false
// turn on resize_observe observer?
// this will observer whenever the element
// resizes and will refresh the background
}
You will need to set resize_observe to true if you use method 1 and your element may change its size at runtime, because then it will need to recreate the chamfered background every time it resizes.