5

For a project I have to cut of the edge of (various) input elements as this is part of the website design. As the background may vary on different screen sizes the edges must be cut transparently that means that you must see the background of the below element where the edge is cut.

This is what I have to achieve:

search field cut edge

With rounded corners I would do the following:

div {
  padding:30px;
  background-color:#c11;
}

input {
  display:block;
  border-top-right-radius:10px;
  border-bottom-left-radius:10px;
  background-color:#fff;
  border:0;
  height:30px;
  width:300px;
  padding:3px 10px;
}
<div>
<input type="text" placeholder="Search ..." />
</div>

However I do not know how to do this square-cut. Do you know a way?

Alireza
  • 2,319
  • 2
  • 23
  • 35
Blackbam
  • 17,496
  • 26
  • 97
  • 150
  • What browsers are you going to support? – Ori Drori Jun 14 '17 at 12:32
  • Its o.k. if only the newest version of chrome, firefox and edge are supported. – Blackbam Jun 14 '17 at 12:33
  • The usual approach of using borders to create “css triangles” (research keyword) should work here, but there’s also a couple of other possible ways (background images, SVG masks, clippath, ...) – CBroe Jun 14 '17 at 12:34
  • The answer of [Rakesh Soni](https://stackoverflow.com/a/44545087/1336174) is supported by most browsers and works in many older versions. – Douwe de Haan Jun 14 '17 at 12:47

4 Answers4

4

You can use clip-path if your target browsers support it. The path can be defined using percentages, so it'll fit any screen size. However, Edge is not supported yet.

It's easier to create the path using Clippy.

div {
  padding: 30px;
  background: linear-gradient(45deg, #c11, blue);
}

input {
  display: block;
  -webkit-clip-path: polygon(calc(100% - 15px) 0, 100% 15px, 100% 100%, 15px 100%, 0 calc(100% - 15px), 0 0);
  clip-path: polygon(calc(100% - 15px) 0, 100% 15px, 100% 100%, 15px 100%, 0 calc(100% - 15px), 0 0);
  background-color: #fff;
  border: 0;
  height: 30px;
  width: 300px;
  padding: 3px 10px;
}
<div>
  <input type="text" placeholder="Search ..." />
</div>
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
4

Easiest way is to add a div on each end and edit their borders. This way your search... placeholder isn't over the line, and you can add a button before then ending span to be a search icon.

.back {
  padding:30px;
  background-color:#c11;
}
.bottom-corner, input, .top-corner, .icon{
  display:inline-block;
  padding:3px 10px;
  vertical-align:middle;
}
.icon{
  background-color:#fff;
  padding-top:10px;
  height:23px;
}
.bottom-corner, .top-corner{
  height: 20px;
}
.bottom-corner{
    border-bottom: 10px solid transparent;
    border-right: 10px solid #fff;
    margin-right: -4px;
}
.top-corner{
  margin-left:-4px;
  border-top: 10px solid transparent;
  border-left: 10px solid #fff;
}
input {
  background-color:#fff;
  border:0;
  height:30px;
  width:300px;
}
<div class="back">
<div class="bottom-corner"></div>
<input type="text" placeholder="Search ..." /><div class="icon">S</div>
<div class="top-corner"></div>
</div>
Sensoray
  • 2,360
  • 2
  • 18
  • 27
  • @PaigeMeinke - it's actually a nice solution. You can replace the elements you've used with pseudo elements. – Ori Drori Jun 14 '17 at 13:03
3

A better way is to use borders

It will support every browser.

See https://jsfiddle.net/kndx9od8/

div.outer {
  padding: 30px;
  background-color: #c11;
}

div.con:after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  border-bottom: 13px solid #c11;
  border-right: 14px solid transparent;
}

div.con:before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  border-top: 13px solid #c11;
  border-left: 14px solid transparent;
}

div.con {
  display: inline-block;
  position: relative;
}

input {
  display: block;
  background-color: #fff;
  border: 0;
  height: 30px;
  width: 300px;
  padding: 3px 10px;
}
<div class="outer">
  <div class="con">
    <input type="text" placeholder="Search ..." />
  </div>
</div>
Rakesh Soni
  • 1,293
  • 2
  • 11
  • 27
  • Just a suggestion: maybe use a div instead of a span? Because some browsers do not allow non-inline elements (input is an inline-block) inside spans ([source](https://stackoverflow.com/questions/11314668/what-elements-can-a-span-tag-contain-in-html5)) They'll probably render it alright, but just for the sake of valid HTML. – Douwe de Haan Jun 14 '17 at 12:50
  • Yes you are right but don't you think `display: inline-block;` to span will do the work – Rakesh Soni Jun 14 '17 at 13:00
  • It would work, yes, but the semantics would be wrong. It would be like putting a div inside a h1. It works, but it is not valid. – Douwe de Haan Jun 14 '17 at 13:02
  • 1
    @DouwedeHaan Updated the answer, Thanks – Rakesh Soni Jun 14 '17 at 13:06
  • Hum actually the corners are not transparent: If you apply `background:linear-gradient(to right, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%);` it does not work anymore. – Blackbam Jun 14 '17 at 13:18
  • @DouwedeHaan inline-block is a CSS thing. It's perfectly (HTML5) valid to put an input into a span as well as a label for example. div and span have the same semantics: none. Then visually you'll probably have to set the CSS display property to anything else than the default for a span (inline-block, flex, etc) – FelipeAls Jun 14 '17 at 13:30
  • @FelipeAls You're right. I read through some documentation again and confused the input with a div. A div is not allowed inside a span, but an input element is. (the w3c validator also returns errors if you put a div inside a span) – Douwe de Haan Jun 14 '17 at 13:33
  • @Blackbam if there is different background then you have to change the border color of the `div.con:after` `div.con:before` See https://jsfiddle.net/kndx9od8/2/ – Rakesh Soni Jun 14 '17 at 15:43
  • @RakeshSoni Sure but if a gradient or a picture is used as background the corner is visible and not transparent – Blackbam Jun 14 '17 at 16:14
1

Here is another option, using transform: skew() and pseudo elements

It works on all backgrounds, has a simple and easy to change code and is quite dynamic too, when it comes to different input width's/height's.

div {
  padding:30px;
  background-color:#c11;
  background: linear-gradient(to right, darkred, #c11);
}
input {
  display:block;
  background-color:#fff;
  border:0;
  height:30px;
  width:300px;
  padding:3px 0px;
  outline: none;
}

div:nth-child(2) input {
  width: 400px;
  height:40px;
  font-size: 25px;
}

/* cut corners */
span {
  position: relative;
  display: inline-block;
  padding: 0 15px;
  overflow: hidden;
}
span::before,
span::after {
  content: '';
  position: absolute;
  left: 0; top: 0;
  width: 15px; bottom: 0;
  background-color: white;
  transform: skewY(45deg);
  transform-origin: right top;
}
span::after {
  left: auto; right: 0; 
  transform-origin: left top;
}
<div>
  <span>
    <input type="text" placeholder="Search ..." />
  </span>
</div>

<div>
  <span>
    <input type="text" placeholder="Search ..." />
  </span>
</div>
Asons
  • 84,923
  • 12
  • 110
  • 165