Clipping or Chamfering Corners of Image to See Background

Clipping or chamfering corners of image to see background

Using Transforms (so CSS3 solution only)

There is a small amount of imprecision in the following method, and it has two "coding" drawbacks:

  1. Two wrappers needed on the img
  2. Need to know the size of the image (which may not always be a drawback if images are set sizes or if javascript is used to give width/height info).

It does, however, degrade nicely back to square corners for IE8 and lower.

The core idea is to size the outer wrapper and hide its overflow, properly size, rotate, and scale down the inner wrapper to create the chamfered corners (which also has overflow hidden), then reverse the rotation and scale back up, and reposition if needed the img nested inside. The method is robust enough to get some fairly decent borders set up if desired, though the rendering of such borders on browsers varies as to quality.

Here's the fiddle.

HTML (basic form)

The span could be a div.

<span class="chamfer">
<span>
<img src="http://placehold.it/351x151" />
</span>
</span>

CSS (basic form)

.chamfer {
overflow: hidden;
display: inline-block; /* could be "block" */
margin: 25px; /* for demo only */
/* Because of the rotations following, it seems like an odd
number in width and height worked more consistently, as
it gives a "middle" pixel by which to transform the rotation
off of
*/
width: 351px; /* width of image */
height: 151px; /* height of image */
}

.chamfer > span {
overflow: hidden;
display: inline-block; /* could be "block" */
-moz-transform-origin: 50% 50%;
-webkit-transform-origin: 50% 50%;
-o-transform-origin: 50% 50%;
-ms-transform-origin: 50% 50%;
transform-origin: 50% 50%;
/* The rotation gets the chamfer angle
the scale sets the "size" of the cut
though not very precisely (exact px height
is not possible to set explicitly.
*/
-moz-transform: rotate(45deg) scale(.9);
-webkit-transform: rotate(45deg) scale(.9);
-o-transform: rotate(45deg) scale(.9);
-ms-transform: rotate(45deg) scale(.9);
transform: rotate(45deg) scale(.9);
/* top/bottom padding is image width (351px)
minus the image height (151px) = 200px divided by 2;
if the image were taller than wide, then this
would become (iH - iW) / 2 for the left/right padding
*/
padding: 100px 0;
margin-top: -100px; /* adjust for the padding */
/* the following helped "square" the item better */
width: 100%;
height: 100%;
}

.chamfer img {
display: inline-block; /* could be "block" */
-moz-transform-origin: 50% 50%;
-webkit-transform-origin: 50% 50%;
-o-transform-origin: 50% 50%;
-ms-transform-origin: 50% 50%;
transform-origin: 50% 50%;
/* The rotation is reversing the wrapper rotation
to put the image horizontal again, while the scale
is the inverse of the wrapper's scale, so here
it is ( 1 / 0.9 ) = 1.11, to scale the image back
up to correct size
*/
-moz-transform: rotate(-45deg) scale(1.11);
-webkit-transform: rotate(-45deg) scale(1.11);
-o-transform: rotate(-45deg) scale(1.11);
-ms-transform: rotate(-45deg) scale(1.11);
transform: rotate(-45deg) scale(1.11);
}

HTML (smaller chamfer with 2px border)

See the above fiddle for a "larger" chamfer with 10px border version as well.

Of course, if all your images were getting a set sized border, you would just make this just like your base html above, and not do override classes as I have here.

<span class="chamfer small b2">
<span>
<img src="http://placehold.it/351x151" />
</span>
</span>

CSS (overrides the basic css above)

See the above fiddle for a "larger" chamfer with 10px border version as well.

Of course, if all your images were getting a set sized border, you would just make these the values of your base css, and not do it in separate classes as defined here.

.b2 * { 
border: 2px solid black;
}

.chamfer.b2 { /* 2px border */
width: 355px; /* 4px added for the 2px border */
height: 155px; /* 4px added for the 2px border */
}

.chamfer.b2 > span {
margin-top: -102px; /* the extra 2px is to accomodate top border of 2px */
margin-left: -2px; /* this is for the 2px left border */
}

.chamfer.small > span {
/* changed the scale for a smaller cut */
-moz-transform: rotate(45deg) scale(.96);
-webkit-transform: rotate(45deg) scale(.96);
-o-transform: rotate(45deg) scale(.96);
-ms-transform: rotate(45deg) scale(.96);
transform: rotate(45deg) scale(.96);
}

.chamfer.small img {
/* scale changed on wrapper to .96 so scale changes on
image to ( 1 / 0.96 ) = 1.042.
*/
-moz-transform: rotate(-45deg) scale(1.042);
-webkit-transform: rotate(-45deg) scale(1.042);
-o-transform: rotate(-45deg) scale(1.042);
-ms-transform: rotate(-45deg) scale(1.042);
transform: rotate(-45deg) scale(1.042);
}

Chamfered border different container color CSS

You may use the pseudo element and rotate them on top(over) of the container with a little difference from your method.

Draw an inset shadow instead a border to your container.

Draw squares with a white background (as container) with borders.

Rotate the square and hide part of them overflowing from container.

DEMO


.chamfered-box{
margin:1em auto;
width: 440px;
padding:5px;
position: relative;
overflow:hidden;
background: white;
box-shadow: inset 0 0 0 1px #149E4B;

}

.chamfered-box::before, .chamfered-box::after{
width: 20px;
height: 20px;
background: #fff;
content: '';
position: absolute;
bottom: 0;
border: 1px solid #149E4B;
transform:rotate(45deg);
}

.chamfered-box::after{
right: -11px;
bottom: -11px;

}

.chamfered-box::before{
left: -11px;
top: -11px;

}

Div Backgrounds That Overlap At The Corner

Yes, this is very possible with CSS.

Here is a technique using a rotated div and :before pseudo element. This looks like a long explanation, but the basic principal is pretty straight forward once you start poking around.

Compatibility: IE9 + and all modern browsers — The transform property in IE9 requires the -ms- prefix and Safari requires the -webkit- prefix. They should be placed before the unprefixed property.

The wrapper

The wrapper is used to clip the slanted corners of each div.

  • Provide a suitable max and min width
  • Clip its children with overflow: hidden

The div

The div is used to create the slant by clipping its childrens bottom right corner.

  • Rotate with transform: rotate()
  • Clip its children with overflow: hidden
  • Blow the width out with width: 200% so that the corners are clipped by the wrapper
  • Move every div (except the first div) up with a negative margin
  • Change the z-order with z-index so that each div is overlapped by the div before it

The :before pseudo element

The :before provides the actual background image without any extra markup.

  • Counter the div parents rotation by the same number of degrees
  • Provide the background image
  • Shift as needed with transform-origin

The straight edge is provided by the bottom edge of the image and the corner is cut off by the parent. The image must be quite large to overlap the width of its parent.

Full Example

Example with prefixes.



.wrap {

margin: 0 auto;

max-width: 1000px;

min-width: 660px;

overflow: hidden;

background: #EEE;

}

.wrap > div {

transform: rotate(-15deg);

height: 700px;

width: 200%;

overflow: hidden;

transform-origin: 0 90%;

position: relative;

z-index: 10;

}

.wrap > div:before {

content: '';

display: block;

width: 100%;

height: 100%;

background: url(http://lorempixel.com/output/food-q-c-1500-1000-2.jpg) no-repeat;

transform: rotate(15deg);

position: absolute;

transform-origin: 30% 0;

}

.wrap > div:nth-child(n+2) {

margin-top: -140px;

}

.wrap > div:nth-child(2):before {

background-image: url(http://lorempixel.com/output/people-q-c-1500-1000-10.jpg);

}

.wrap > div:nth-child(3):before {

background-image: url(http://lorempixel.com/output/technics-q-c-1500-1000-3.jpg);

}

.wrap > div:nth-child(2) {

z-index: 9;

}

.wrap > div:nth-child(3) {

z-index: 8;

}
<div class="wrap">

<div></div>

<div></div>

<div></div>

</div>

How to draw a shape using a piece of image in php

Preprocessing the image is vital

Whether done manually by you, or on the fly somehow through a GD library, you absolutely at the least need to take the image you state you are receiving...

Sample Image

...and crop and tighten it to make it clean like this (with no white space around the edges and the notch/cut removed):

Sample Image

Then you have an image you can actually work with.

Otherwise, PURE CSS / JAVASCRIPT

NOTE: I am not doing the javascript here. It would be used to dynamically set the element sizing as seen in the html.

Normally I would use a judicious amount of :before and ':after' pseudo elements to keep the html less cluttered, but since you need dynamic sizing of the frame, then we need to use a number of nested div elements to set dynamic styles for widths and heights that are critical to some of the div elements (some of which would still be pseudo elements if javascript could access those or if dynamic sizing was not needed).

NOTE: So far I have only tested this in Chrome and Firefox. Really old browsers are for sure going to fail miserably.

/* implementation of framing */

.frameit {

/* width and height must be set dynamically by javascript see html */

position: relative;

box-sizing: border-box;

overflow: hidden;

padding: 20px; /* at least border size */

}

.frameit:before,

.frameit:after,

.frameit .sides > div,

.frameit .corner > div {

position: absolute;

background-image: url(http://i.stack.imgur.com/vAgqj.jpg);

background-size: 100% 20px; /* 100% and border size */

height: 20px; /* equal to border width of frameit div */

}

.frameit:before {

content: '';

top: 0;

left: 0;

right: 0;

}

.frameit:after {

content: '';

bottom: 0;

left: 0;

right: 0;

}

.frameit .sides {

position: absolute;

top: 0;

right: 0;

bottom: 0;

left: 0;

z-index: 1;

}

.frameit .sides > div {

/* width must be set dynamically by javascript see html */

height: 20px;

}

.frameit .sides > div:first-child {

top: 0;

left: 20px; /* border width */

transform-origin: 0 0;

transform: rotate(90deg);

}

.frameit .sides > div:last-child {

bottom: 0;

right: 20px; /* border width */

transform-origin: 100% 100%;

transform: rotate(90deg);

}

.frameit .sides ~ .corner { /* all corners */

position: absolute;

z-index: 2;

width: 29px; /* square root of ((border-width squared) x 2) round up */

height: 29px; /* match width */

overflow: hidden;

}

.frameit .TL {

top: 0;

left: 0;

transform-origin: 0 0;

transform: rotate(-45deg);

}

.frameit .TL > div {

top: inherit;

left: inherit;

transform-origin: inherit;

transform: rotate(45deg);

}

.frameit .TR {

top: 0;

right: 0;

transform-origin: 100% 0;

transform: rotate(45deg);

}

.frameit .TR > div {

top: 0;

right: 0;

transform-origin: 100% 0;

transform: rotate(-45deg);

}

.frameit .BR {

bottom: 0;

right: 0;

transform-origin: 100% 100%;

transform: rotate(-45deg);

}

.frameit .BR > div {

bottom: inherit;

right: inherit;

transform-origin: inherit;

transform: rotate(45deg);

}

.frameit .BL {

bottom: 0;

left: 0;

transform-origin: 0 100%;

transform: rotate(45deg);

}

.frameit .BL > div {

bottom: inherit;

left: inherit;

transform-origin: inherit;

transform: rotate(-45deg);

}

/* Optional shading to help define the joint */

.frameit .sides > div:first-child:before,

.frameit .sides > div:last-child:before {

content: '';

position: absolute;

top: 0;

right: 0;

left: 0;

bottom: 0;

background-color: rgba(0,0,0,.07);

}
<div class="frameit" style="width: 200px; height: 300px;">

<!-- top and bottom and overall container

width and height assumed to be set by javacript by user

-->

<div class="sides">

<!-- left and right sides

widths of the children are equal to HEIGHT of container and are

assumed to be set by javacript by user

-->

<div style="width: 300px;"></div>

<div style="width: 300px;"></div>

</div>

<div class="TL corner"><!-- top left bevel --><div style="width: 200px;"></div></div>

<div class="TR corner"><!-- top right bevel --><div style="width: 200px;"></div></div>

<div class="BR corner"><!-- bottom right bevel --><div style="width: 200px;"></div></div>

<div class="BL corner"><!-- bottom left bevel --><div style="width: 200px;"></div></div>

</div>

How can I make angled corners on a UIView?

First you need a path with the angled corners:

- (CGPathRef) makeAnglePathWithRect: (CGRect)rect withSize:(float) s {

CGPoint one = CGPointMake( rect.origin.x +s, rect.origin.y);
CGPoint two = CGPointMake( rect.origin.x + rect.size.width - s, rect.origin.y);

CGPoint three = CGPointMake( rect.origin.x + rect.size.width, rect.origin.y +s);
CGPoint four = CGPointMake( rect.origin.x + rect.size.width, rect.origin.y + rect.size.height -s);

CGPoint five = CGPointMake( rect.origin.x + rect.size.width-s, rect.origin.y + rect.size.height);
CGPoint six = CGPointMake(rect.origin.x+s, rect.origin.y + rect.size.height);

CGPoint seven = CGPointMake(rect.origin.x, rect.origin.y + rect.size.height-s);
CGPoint eight = CGPointMake(rect.origin.x, rect.origin.y + s);

CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path,NULL,one.x, one.y);
CGPathAddLineToPoint(path,NULL,two.x, two.y);
CGPathAddLineToPoint(path,NULL,three.x, three.y);
CGPathAddLineToPoint(path,NULL,four.x, four.y);
CGPathAddLineToPoint(path,NULL,five.x, five.y);
CGPathAddLineToPoint(path,NULL,six.x, six.y);
CGPathAddLineToPoint(path,NULL,seven.x, seven.y);
CGPathAddLineToPoint(path,NULL,eight.x, eight.y);
CGPathAddLineToPoint(path,NULL,one.x, one.y);

return path;
}

Then you need to use the path to specify a mask:

CAShapeLayer *maskLayer = [CAShapeLayer layer];
CGRect bounds = CGRectMake(0.0f, 0.0f, 100, 100); //figure out your bounds

[maskLayer setFrame:bounds];
CGPathRef p = [self makeAnglePathWithRect:bounds withSize:20.0];
maskLayer.path = p;
_myview.layer.mask = maskLayer;

If you want to remove the angles from any corner, fiddle with points one-eight, removing the "s" value. You can change the size of the triangles cut out of the corners with the size parameter.

Is it possible to create an angled corner in CSS?

It's a little difficult keeping the border, but I managed to achieve a close effect using :before and :after elements with a parent container (:before and :after don't work on an img tag)

  1. Add a border to the container

  2. Add a before to block out a corner and offset by -1 to cover the border

  3. Add an after that's slightly offset from the before to create the line inside the cut off

As you can see, the thickness of the 45deg line is a bit of an issue:

.cutCorner {

position:relative; background-color:blue;

border:1px solid silver; display: inline-block;

}

.cutCorner img {

display:block;

}

.cutCorner:before {

position:absolute; left:-1px; top:-1px; content:'';

border-top: 70px solid silver;

border-right: 70px solid transparent;

}

.cutCorner:after {

position:absolute; left:-2px; top:-2px; content:'';

border-top: 70px solid white;

border-right: 70px solid transparent;

}
<div class="cutCorner">

<img class="" src="https://www.google.co.uk/logos/doodles/2013/william-john-swainsons-224th-birthday-5655612935372800-hp.jpg" />

</div>


Related Topics



Leave a reply



Submit