Como definir a largura e altura de uma imagem sem esticá-la?

87

Se eu tiver:

#logo {
    width: 400px;
    height: 200px;
}

então

<img id="logo" src="logo.jpg"/>

vai se esticar para preencher esse espaço. Quero que a imagem permaneça do mesmo tamanho, mas ocupe muito espaço no DOM. Tenho que adicionar um encapsulamento <div>ou <span>? Eu odeio adicionar marcação para estilo.

Paul Tarjan
fonte
Se você ainda estiver no Stack Overflow, gostaria de atualizar a resposta?
mikemaccana

Respostas:

116

Sim, você precisa de um div encapsulante:

<div id="logo"><img src="logo.jpg"></div>

com algo como:

#logo { height: 100px; width: 200px; overflow: hidden; }

Outras soluções (preenchimento, margem) são mais tediosas (porque você precisa calcular o valor correto com base nas dimensões da imagem), mas também não permitem que o contêiner seja efetivamente menor do que a imagem.

Além disso, os itens acima podem ser adaptados com muito mais facilidade para diferentes layouts. Por exemplo, se você quiser a imagem no canto inferior direito:

#logo { position: relative; height: 100px; width: 200px; }
#logo img { position: absolute; right: 0; bottom: 0; }
cletus
fonte
5
Você pode substituir a tag <div> por <figure>: adiciona semântica e você pode dar uma legenda (<figcaption>) para ela, se necessário. developer.mozilla.org/en-US/docs/Web/HTML/Element/figure
Mateus Leon
Além disso, se for para uso de marca, na apresentação do site, use <h1> (se for índice) ou <p> (se for outro), aplicando os atributos title e alt ao <img>, para que você possa adicionar marcação amigável de SEO . Eles também são elementos de nível de bloco, como div, e podem ser invólucros para a funcionalidade de corte.
Mateus Leon
3
Eu não tinha ideia de que Cletus era um desenvolvedor web. Incrível
Piyin
61

Resposta de 2017

O ajuste de objeto CSS funciona em todos os navegadores atuais. Permite que o imgelemento seja maior sem esticar a imagem.

Você pode adicionar object-fit: cover;ao seu CSS.

Dante
fonte
2
Você provavelmente deve mencionar em quais navegadores ele funciona.
Nathan Tuggy de
2
verifique este link para compatibilidade do navegador: caniuse.com/#search=object-fit
Alexee
28

Carregue a imagem como plano de fundo para um div.

Ao invés de:

<img id='logo' src='picture.jpg'>

Faz

<div id='logo' style='background:url(picture.jpg)'></div>

Todos os navegadores irão cortar a parte da imagem que não cabe.
Isso tem várias vantagens sobre envolvê-lo em um elemento cujo estouro está oculto:

  1. Sem marcação extra. O div simplesmente substitui o img.
  2. Centralize facilmente ou defina a imagem para outro deslocamento. por exemplo.url(pic) center top;
  3. Repita a imagem quando for pequena o suficiente. (OK, não sei por que você iria querer isso)
  4. Defina uma cor bg na mesma instrução, aplique facilmente a mesma imagem a vários elementos e tudo o que se aplica a imagens bg.

Atualização: Esta resposta é anterior ao ajuste ao objeto; agora você provavelmente deve usar ajuste de objeto / posição de objeto.

Ainda é útil para navegadores mais antigos, para propriedades extras (como repetição de fundo) e para casos extremos (por exemplo, soluções alternativas para bugs do Chrome com flexbox e posição de objeto e problemas de FF (antigo?) Com grade + autoheight + objeto- ajuste. Divs wrapper em grade / flexbox geralmente fornecem ... resultados não intuitivos.)

SamGoody
fonte
4
Aqueles que deram -1 devem explicar para o benefício de outros usuários. Pessoalmente, fiz isso com excelentes resultados, mesmo no IE6 e Safari no iOS.
SamGoody
Só queria acrescentar - geralmente é uma boa abordagem. As pessoas até especificam coordenadas de posição de fundo para folhas de sprite de imagem como otimização. Uma diferença, no entanto, é que ele não tem o manipulador de eventos de erro que <img> tem
badunk
Também adicionei uma classe ao div com estes conteúdos:background-repeat:no-repeat !important; float:left; width:100px; height:100px;
Nils
2
Alguns navegadores, por padrão, não imprimirão imagens de fundo, portanto, essa pode não ser uma boa abordagem se você quiser permitir que os usuários imprimam essa página.
Bennett McElwee
5
Isso não é semanticamente correto. Se isso é útil, por que o HTML5 está colocando mais tags relacionadas a imagens, para otimizar a semântica, com figcaption, picture? Use a tag img como ela foi projetada e pare de substituir tudo por <div> s.
Mateus Leon
23

CSS3 objeto-fit

Não tenho certeza de até que ponto foi implementado pelo webkit, IE e firefox. Mas o Opera funciona como mágica

object-fitfunciona com conteúdo SVG, mas o mesmo efeito também pode ser obtido definindo o preserveAspectRatio=""atributo no próprio SVG.

img {
  height: 100px;
  width: 100px;
  -o-object-fit: contain;
}

Chris Mills demonstra aqui http://dev.opera.com/articles/view/css3-object-fit-object-position/

o caranguejo
fonte
2
1+ Isso é muito legal. Uma pena que o suporte é limitado. Parece que o Chrome 32 é o primeiro a oferecer suporte sem prefixos de fornecedor.
Josh Crozier de
Isso é fantástico, funciona como um encanto. Apenas adicionar uma única propriedade consertou tudo. Eu só precisava do Chrome e funciona. E sim, sem prefixo do fornecedor. Obrigado.
whyAto8
9
#logo {
    width: 400px;
    height: 200px;

    /*Scale down will take the necessary specified space that is 400px x 200px without stretching the image*/
    object-fit:scale-down;
}
Manoj Selvin
fonte
7

Faça um div e dê uma aula. Em seguida, coloque um img nele.

<div class="mydiv">

<img src="location/of/your/image" ></img>

</div>

Defina o tamanho do seu div e torne-o relativo.

    .mydiv {
        position: relative;
        height:300px;
        width: 100%;
        overflow: hidden;
    }

então estilize sua imagem

img {
    width: 100%;
    height: auto;
    overflow: hidden;
}

espero que ajude

Sabba Keynejad
fonte
2

Você pode usar o seguinte:

.width100 {
  max-width: 100px;
  height: 100px;
  width: auto;
  border: solid red;
}
<img src="https://www.gravatar.com/avatar/dc48e9b92e4210d7a3131b3ef46eb8b1?s=512&d=identicon&r=PG" class="width100" />

PurTahan
fonte
1

Devo adicionar um <div> ou <span> encapsulante?

Eu acho que você faz. A única coisa que vem à mente é o preenchimento, mas para isso você teria que saber as dimensões da imagem de antemão.

Pekka
fonte
0

você pode tentar definir o preenchimento em vez da altura / largura.

Abençoe Yahu
fonte
0

O que posso pensar é esticar a largura ou a altura e deixá-lo redimensionar no aspecto de proporção. Haverá algum espaço em branco nas laterais. Algo parecido com a forma como uma tela ampla exibe uma resolução de 1024x768.

mauris
fonte
0

Se usar flexbox é uma opção válida para você (não precisa suportar navegadores antigos), verifique minha outra resposta aqui (que é possivelmente uma duplicata desta):

Basicamente, você precisa envolver sua tag img em uma div e seu css ficaria assim:

.img__container {
    display: flex;
    padding: 15px 12px;
    box-sizing: border-box;
    width: 400px; height: 200px;

    img {
        margin: auto;
        max-width: 100%;
        max-height: 100%;
    }
}
Rafaelbiten
fonte
-1

Esta é uma questão muito antiga, mas eu tive exatamente o mesmo problema irritante em que tudo funcionava bem para o Chrome / Edge (com a propriedade de ajuste do objeto), mas a mesma propriedade css não funcionava no IE11 (já que não é compatível com o IE11), acabei usando HTML5 elemento "figura" que resolveu todos os meus problemas.

Eu, pessoalmente, não usei a tag DIV externa, pois isso não ajudou em nada no meu caso, então evitei o DIV externo e simplesmente substituí pelo elemento 'figura'.

O código a seguir força a imagem a ser reduzida / reduzida de maneira adequada (sem alterar a proporção de aspecto original).

<figure class="figure-class">
  <img class="image-class" src="{{photoURL}}" />
</figure>

e classes css:

.image-class {
    border: 6px solid #E8E8E8;
    max-width: 189px;
    max-height: 189px;
}

.figure-class {
    width: 189px;
    height: 189px;
}
nakul2013
fonte