Como cortar e centralizar automaticamente uma imagem

158

Dada qualquer imagem arbitrária, quero cortar um quadrado do centro da imagem e exibi-lo dentro de um determinado quadrado.

Esta pergunta é semelhante a esta: CSS exibe uma imagem redimensionada e cortada , mas não sei o tamanho da imagem, portanto não posso usar margens definidas.

Jonathan Ong
fonte
1
O elemento deve ser uma tag de imagem ou pode ser uma div com uma propriedade de imagem de plano de fundo?
Russ Ferri
contanto que eu possa definir a imagem através do meu sistema de modelos, isso não importa. meio feio, mas acho que os estilos embutidos funcionarão.
31812 Jonathan Ong

Respostas:

318

Uma solução é usar uma imagem de plano de fundo centralizada em um elemento dimensionado para as dimensões cortadas.


Exemplo básico

.center-cropped {
  width: 100px;
  height: 100px;
  background-position: center center;
  background-repeat: no-repeat;
}
<div class="center-cropped" 
     style="background-image: url('http://placehold.it/200x200');">
</div>


Exemplo com imgtag

Esta versão mantém a imgtag para que não percam a capacidade de arrastar ou clicar com o botão direito do mouse para salvar a imagem. Agradecemos a Parker Bennett pelo truque da opacidade.

.center-cropped {
  width: 100px;
  height: 100px;
  background-position: center center;
  background-repeat: no-repeat;
  overflow: hidden;
}

/* Set the image to fill its parent and make transparent */
.center-cropped img {
  min-height: 100%;
  min-width: 100%;
  /* IE 8 */
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
  /* IE 5-7 */
  filter: alpha(opacity=0);
  /* modern browsers */
  opacity: 0;
}
<div class="center-cropped" 
     style="background-image: url('http://placehold.it/200x200');">
  <img src="http://placehold.it/200x200" />
</div>


object-fit/-position

Veja navegadores suportados .

A especificação de imagens CSS3 define as propriedades object-fite object-positionque, juntas, permitem maior controle sobre a escala e a posição do conteúdo da imagem de um imgelemento. Com estes, será possível alcançar o efeito desejado:

.center-cropped {
  object-fit: none; /* Do not scale the image */
  object-position: center; /* Center the image within the element */
  height: 100px;
  width: 100px;
}
<img class="center-cropped" src="http://placehold.it/200x200" />

Russ Ferri
fonte
45
Você pode usar background-size: cover;para reduzir a imagem ou preencher a div adequadamente, mantendo a proporção original.
31413 Nick
7
Ao usar imagem de fundo você deve adicionar background-size: tampa para adequadamente o tamanho da imagem recortada: Veja jsfiddle.net/bw6ct
Kris Erickson
2
Disseram-me que hoje em dia o Google conhece imagens transparentes e ocultas, portanto, imgos atributos das altformigas titleserão perdidos para o seu SEO.
21414 Victor Gallieni /
6
No webkit, você também pode usar object-fit: cover;diretamente a tag img, que parece um pouco mais semântica.
Ben
2
Eu costumava objeto-fit: tampa para obter o meu efeito desejado de não perder a relação de aspecto, cobrindo a praça, e corte, se necessário
Daniel Handojo
79

Eu estava procurando uma solução CSS pura usando imgtags (não da maneira da imagem de fundo).

Encontrei essa maneira brilhante de atingir a meta em miniaturas de culturas com css :

.thumbnail {
  position: relative;
  width: 200px;
  height: 200px;
  overflow: hidden;
}
.thumbnail img {
  position: absolute;
  left: 50%;
  top: 50%;
  height: 100%;
  width: auto;
  -webkit-transform: translate(-50%,-50%);
      -ms-transform: translate(-50%,-50%);
          transform: translate(-50%,-50%);
}
.thumbnail img.portrait {
  width: 100%;
  height: auto;
}

É semelhante à resposta de @Nathan Redblur, mas também permite imagens de retrato.

Funciona como um encanto para mim. A única coisa que você precisa saber sobre a imagem é se ela é retrato ou paisagem para definir a .portraitclasse, então tive que usar um pouco de Javascript para esta parte.

gluecksmelodie
fonte
3
Esteja ciente de que as transformações CSS só estão disponíveis no IE 9 e acima.
Simon Médio
5
Essa deve ser a resposta.
Wes Modes
A OP disse "imagem arbitrária" para não saber de antemão se a imagem era mais alta do que larga.
opyate 25/10
11
Se você colocar min-height: 100%, min-width: 100%; em vez de altura: 100%; largura: auto; você não precisa da classe img.portrait.
user570605
1
melhor solução combinada com @ user570605 sugestão
albanx
45

Tente isto: Defina as dimensões de corte da imagem e use esta linha no seu CSS:

object-fit: cover;
Roych
fonte
3
não muito bem suportado: caniuse.com/#feat=object-fit EDIT: na verdade, como de costume, apenas os navegadores MS falham nisso ... isso representa uma grande parte do uso: /
Brian H.
1
Isto faz exatamente o que eu preciso :)
hcarreras
1
Os únicos navegadores amplamente usados ​​que não oferecem suporte a isso são o Internet Explorer 11 e o Edge. Dependendo do seu público, o suporte no momento é provavelmente de 85 a 90%, o que pode tornar isso viável em alguns cenários.
Husky
rei! solução incrível !!
itzhar
1
ther é um bom tutorial sobre isso: medium.com/@chrisnager/...
Pietro La Grotta
23

Exemplo com imgtag mas sembackground-image

Essa solução mantém a imgmarca para que não percam a capacidade de arrastar ou clicar com o botão direito do mouse para salvar a imagem, mas sem background-imageapenas centralizar e cortar com css.

Mantenha a proporção perfeita, exceto em imagens muito altas. (verifique o link)

(ver em ação)

Marcação

<div class="center-cropped">
    <img src="http://placehold.it/200x150" alt="" />
</div>

CSS

div.center-cropped {
  width: 100px;
  height: 100px;
  overflow:hidden;
}
div.center-cropped img {
  height: 100%;
  min-width: 100%;
  left: 50%;
  position: relative;
  transform: translateX(-50%);
}
Nathan Redblur
fonte
Experimente esta ... se a imagem for menor que o contêiner que será centralizado, caso contrário, ela será
cortada
8

Criei uma diretiva angularjs usando as respostas @ Russ e @ Alex

Pode ser interessante em 2014 e além: P

html

<div ng-app="croppy">
  <cropped-image src="http://placehold.it/200x200" width="100" height="100"></cropped-image>
</div>

js

angular.module('croppy', [])
  .directive('croppedImage', function () {
      return {
          restrict: "E",
          replace: true,
          template: "<div class='center-cropped'></div>",
          link: function(scope, element, attrs) {
              var width = attrs.width;
              var height = attrs.height;
              element.css('width', width + "px");
              element.css('height', height + "px");
              element.css('backgroundPosition', 'center center');
              element.css('backgroundRepeat', 'no-repeat');
              element.css('backgroundImage', "url('" + attrs.src + "')");
          }
      }
  });

ligação violino

mraaroncruz
fonte
3
Hiya downvoters. Deixe um comentário para que eu possa atualizar minha resposta se houver um erro. Não gosto de dar informações falsas. Felicidades.
mraaroncruz
Não é um infrator, mas esta não é uma pergunta angular e sua resposta é irrelevante. @pferdefleisch
mawburn
1
@ queima que faz sentido. Já faz 3 anos e isso provavelmente parece um pouco fora de lugar ou desagradável agora. Vou deixar assim porque as votações positivas no meu comentário me dizem que pelo menos algumas pessoas podem achar útil (ou simplesmente não gostam de votações negativas sem comentários).
precisa saber é o seguinte
2

Tente o seguinte:

#yourElementId
{
    background: url(yourImageLocation.jpg) no-repeat center center;
    width: 100px;
    height: 100px;
}

Tenha em mente que widthe heightsó irá funcionar se o seu elemento DOM tem layout (um bloco elemento exibida, como um divou um img). Se não estiver (um intervalo, por exemplo), adicione display: block;às regras de CSS. Se você não tiver acesso aos arquivos CSS, solte os estilos embutidos no elemento

Alejandro Rizzo
fonte
na maioria dos casos, esse CSS é usado repetidamente com imagens diferentes. portanto, é inevitável definir a imagem de fundo em linha.
Raptor
0

Há outra maneira de cortar a imagem centralizada:

.thumbnail{position: relative; overflow: hidden; width: 320px; height: 640px;}
.thumbnail img{
    position: absolute; top: -999px; bottom: -999px; left: -999px; right: -999px;
    width: auto !important; height: 100% !important; margin: auto;
}
.thumbnail img.vertical{width: 100% !important; height: auto !important;}

A única coisa que você precisará é adicionar a classe "vertical" às imagens verticais. Você pode fazer isso com este código:

jQuery(function($) {
    $('img').one('load', function () {
        var $img = $(this);
        var tempImage1 = new Image();
        tempImage1.src = $img.attr('src');
        tempImage1.onload = function() {
            var ratio = tempImage1.width / tempImage1.height;
            if(!isNaN(ratio) && ratio < 1) $img.addClass('vertical');
        }
    }).each(function () {
        if (this.complete) $(this).load();
    });
});

Nota: "! Important" é usado para substituir possíveis atributos de largura e altura na tag img.

Vedmant
fonte