Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
734 views
in Technique[技术] by (71.8m points)

css - Clipping or chamfering corners of image to see background

I have a design where corners of images are cut in a 45° angle. For the time being, it’s achieved by masking it with an absolutely positioned span, which has a transparent background image set with the corner “cut” in opaque white. This is far from ideal, first because of the additional span, second because the background of the image is not homogeneous white.

I intend to generate transparent PNGs later, but it would be more elegant and – considering the images are photographs – less bandwith-intensive to use JPEGs and CSS. The new CSS mask property seemed promising, but as I understand it does not provide the ability, to ?mask through” to the background of the element, does it?

So my question is, is there any new CSS property out there which I’m not aware of and would allow me to do this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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);    
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...