Bruno Dulcetti



Arquivos:

Categorias:

  • Amizade:

  • Artigos

  • Links:

    O meu, o seu, o nosso espaço!

    » Resposta do Desafio: Como “cropar” uma foto com CSS

    Como prometido, estou aqui pra postar a “resposta” do “desafio” que postei ontem aqui no Blog.

    Algumas sugestões, soluções, bem próximas da que eu arrumei e achei melhor. Vou tentar explicar detalhadamente porque não utilizei tal solução, porque fiz dessa forma, o que não rola, suporte, etc.

    Sugestões

    O juliano postou uma solução com background, mas como eu disse depois, não é possível, pois o conteúdo é dinâmico, portanto, não rola colocar como background.

    A do Michael ficou um pouco extensa, com um span como se fosse uma “máscara”, mostrando somente a área necessária. Mas como sabemos, o IE não nos ajuda quase nunca 😛 e não funciona a pseudo-classe :hover, somente em link, mas somente alguns atributos são suportados.

    Sobral e Mico citaram o clip, mas como citei acima, o IE não suporta a pseudo-classe e somente alguns atributos são suportados, o que não é o caso do clip, infelizmente. Fora que o clip só funciona em elementos com position absolute ou fixed.

    A do Alisson ficou +ou- parecido com a que eu implementei, mas faltaram alguns detalhes, algumas mudanças, para que funcionasse perfeitamente.

    Primeira Solução

    Chega de conversa e vamos para a primeira solução. Nessa eu utilizei o clip, como o mico e o sobral citaram, mas como falei, preciso da pseudo-classe :hover funcionando perfeitamente no IE, com isso, tive que utilizar um arquivo .htc, que faz com que o IE aceite o hover em qualquer tag.

    Código HTML

    <div id="fotos">
    <a href="#" title="" class="cropFoto"><img src="thumb.jpg" alt="Foto" /></a>
    </div>

    Código CSS

    * {margin:0;padding:0;}

    body {padding:20px;}
    ul {list-style:none;}
    img {border:0;}

    #fotos {width:186px;}
    #fotos * {display:block;}

    #fotos .cropFoto {background-color:#E70202;height:116px;position:relative;}
    #fotos .cropFoto img {position:absolute;}
    #fotos .cropFoto:hover img {clip:rect(3px 183px 113px 3px);}

    Um código simples e curto. Não vou ficar detalhando coisas desnecessárias, somente o que eu acho relevante para o entendimento para um desenvolvedor intermediário, etc.

    O link recebe a classe cropFoto, com a cor de background que eu quero que fique a “borda” em volta da imagem. Recebe o valor de altura igual a altura da imagem e recebe um position relative.

    A imagem dentro do link recebe um position absolute, lembram que o clip só funciona em elementos com position absolute e fixed? Por isso que também tive que colocar o position relative dentro do link, para a imagem não se basear de acordo com o body, etc.

    Veja o exemplo funcionando.

    Para mais infos sobre position, visite o artigo que escrevi no imasters sobre o assunto.

    Tá Bruno, mas não funcionou no IE

    Exatamente. Graças a ele, precisamos utilizar a gambiarra que falei anteriormente, pra funcionar a pseudo-classe :hover. Percebam que só funciona em link, e estou utilizando em um link, mas mesmo assim não funcionou o clip. Ele só aceita alguns atributos no :hover

    É só anexarmos o csshover.htc no html, que funciona no IE. Baixe o arquivo .htc aqui e cole o código abaixo entre as tags <head> e </head>:

    Código HTML

    <!--[if IE]>
    <style type="text/css">
    body {behavior:url(csshover.htc);}
    </style>
    <![endif]-->

    Veja o exemplo correto funcionando.

    Legal Bruno, funcionou direitinho…

    Exatamente, mas sempre existe um porém. Temos vantagens em utilizar esse htc, pois teremos hover em todas as tags, mas, como nem tudo é perfeito, temos alguns problemas:

    • Esse é um projeto grande, com muito volume de informação, conteúdo, etc. Teremos uma quantidade considerável de imagens com esse efeito no hover;
    • Necessita que o servidor tenha o mime type configurado para ele: text/x-component
    • Ele faz uma busca por :hover em TODO o stylesheet da página. Onde ele achar o :hover, vai adicionar um evento javascript onmouseover para que o elemento se comporte da forma correta.
    • O problema é que esse processamento é no cliente e o tempo que ele leva para fazer isso vai depender do tamanho do CSS, do HTML, além do poder do computador do cara, ou seja, quanto maior o CSS e HTML, mais tempo para execução o efeito vai levar, e como o projeto é grande, queremos sempre a melhor forma, otimizar, etc.

    Por essas e outras, tive que buscar uma outra opção, modo, de implementar esse efeito, somente por CSS, sem colocar htc, js, nem nada.

    Segunda Solução

    Eis que surge uma idéia no início, meio bizarra pra utilizar como solução. E não é que deu certo? 😀

    O código HTML utilizado foi o mesmo do exemplo anterior. Abaixo segue o CSS:

    Código CSS

    * {margin:0;padding:0;}

    body {padding:20px;}
    ul {list-style:none;}
    img {border:0;}

    #fotos {width:186px;}
    #fotos * {display:block;}

    #fotos .cropFoto {overflow:hidden;height:116px;width:186px;}
    #fotos .cropFoto:hover {border:3px solid #E70202;height:110px;width:180px;}

    Veja este exemplo funcionando.

    Legal Bruno… Funcionou só com CSS né?

    Então, +ou-. Ainda não está 100%, porque dá um efeito que a imagem se move por causa da borda colocada no link.

    É um código bem simples, de fácil entendimento. A imagem o link estão como block, o link está com a largura e altura setada de acordo com o tamanho da imagem. Esse tamanho pode variar, dependendo da imagem, é só modificar no CSS pro tamanho da imagem.

    No hover do link, ele diminui 6px de altura e largura e ganha 3px de borda em volta dele, totalizando a mesma largura e altura.

    O overflow hidden do link serve pra que mesmo que a imagem seja maior que o link, o que é o caso no estado :hover, ela fique oculta, não quebrando o layout, etc.

    Entendi Bruno. E como resolvo pra ficar 100%, sem parecer que a imagem se move?

    Simples, apenas uma linha de CSS, colocando uma margem pra imagem, no hover do link:
    #fotos .cropFoto:hover img {margin:-3px 0 0 -3px;}

    Veja o exemplo final funcionando.

    Agora sim hein 😀 Graças a Deus, o IE aceita o atributo margin na pseudo-classe hover do link no CSS. 😉

    Conclusões

    Bom, é uma solução simples, tranqüila, mas que nem sempre vem a cabeça facilmente, rápido. Testei no IE 6, IE 7, Firefox, Opera, Firefox Mac, Safari e todos funcionaram perfeitamente, sem nenhuma diferença.

    Algumas coisas precisam de alguns detalhes pra funcionar, por exemplo, o display: block no link, na imagem também pra ficar correto, se fosse usar o clip, lembrar do position: absolute, lembrar do overflow: hidden, etc, etc, etc.

    Sempre tem essas pequenas coisas que são essenciais saber no CSS, que você pega com a prática.

    Finalizando

    Bom, é isso. Qualquer dúvida, correção ou solução melhor, é só comentar que eu posto aqui 😉

    Aquele abraço.

    [BBL]css, desafio, dicas, webstandards[/BBL]

    [ 26/jun/2007 às 15:58hrs ] [ Por Bruno Dulcetti ] Comentários 19 Comentários |

    Categorias: CSS,Webstandards

    19 Comentários no Post "Resposta do Desafio: Como “cropar” uma foto com CSS"

    Postar no Rec 6

    1. Boa.. tava interessado para ver como voce iria resolver isso. Confesso que logo de inicio eu pensei na possibilidade do background mas como você disse que as imagens são dinâmicas. Depois de tudo isso me restou uma duvida, que nao é referebte a solução mas sim a questão. Mesmo que as imagens sejam montadas dinamicamente porque você nao usa o atributo, style=’backgroun…..’ ? Me responda por e-mail por favor. Não tenho costume de voltar a um post e ver se meu comentário foi respondido =)

    2. E ae rapaz. Por alguns motivos:

      • Não é recomendada a utilização do atributo style, pois não estará trabalhando em camadas como a W3C recomenda e eu, pessoalmente, prefiro;
      • Teria que mudar a estrutura do publicador, para ao invés de publicar a imagem, publicasse o caminho no style. E se tratando de Globo.com, você já deve imaginar a grandiosidade e o auê que isso iria acarretar =D;
      • A imagem, nesse caso, não faz parte de estilo, visual, design e sim, parte do conteúdo do site, portanto, não é recomendada a utilização como background;

      Basicamente isso 😉

      Aquele abraço.

    3. Seria taum bom se os browsers facilitassem nossas vidas não é? Pena que isso ainda está dificil de acontecer.
      Valeu pela dica. acho que vou precisar algum dia

      Abraço

    4. é rapaz… mas ainda vai demorar muito…

      mas pense pelo lado bom, é um diferencial para os desenvolvedores que conhecem, saibam lidar e como resolver tais bugs…

      akele abraço.

    5. Legal Bruno… mas ter que definir uma largura e altura para esse efeito não é complicado para imagens que vem de um banco de dados, por exemplo, e com tamanho variado? Ter que modificar o CSS em cada matéria publicada ou criar várias classes para diferentes possíveis tamanhos deve atrapalhar um conteúdo dinâmico. O que você acha?

      Falou, Bruno.

    6. Falae xará.

      Largura não é necessário, pois como a imagem e o link estão como block, eles pegam a largura do pai.

      Em relação a altura, sim é verdade, precisamos setar a altura e isso realmente é chato. Mas isso se resolve com uma boa estruturação, sabendo que dentro de cada box a imagem terá tal tamanho, etc.

      Aqui na Globo.com, nesse projeto, temos padrões de tamanho e lugares onde esse efeito irá ocorrer, com isso, fica mais fácil a implementação.

      Sim, temos que ter várias classes, ou então, como os efeitos serão em divs diferentes, setar no CSS que o efeito nessa div terá tal altura, etc.

      O conteúdo dinâmico não chega a atrapalhar não, só complica um pouco mais pro meu lado, criar as classes com os tamanhos corretos, mas isso não é nada demais. 😉

      E também podemos fazer por javascript, pegando a altura da imagem e setando por js mesmo a altura da div igual a altura da imagem.

      Aquele abraço.

    7. beleza Brunão… nesse caso usar javascript vai dar uma obstruidazinha né, hehe. Valeu, sucesso.

    8. Ótimo, Bruno…
      que tal mais desses desafios, isso ajuda o pessoal a pensar, rachar a cuca em uma solução. Parabéns 🙂

    9. eu to enganado ou isso ai e uma foto em JPG que leva a um site um link etc??

    10. […] Sim. De novo. Mas relaxem, é um efeito diferente do que eu fiz para o efeito de borda interna dos sites da Globo.com, e que eu creio que muitos já quiseram fazer e não conseguiram, etc. […]

    11. […] no link http://www.brunodulcetti.com/blog/2007/06/26/resposta-do-desafio-como-cropar-uma-foto-com-css.html Tags BlogBlogs: [ css, desafio, dicas, webstandards ] [ 25/Jun/2007 às 12:15hrs ] [ Por Bruno […]

    12. Fabiano Carboni | 18/abr/2008 às 16:39

      Fala Bruno.

      Seu site serviu de guia pra mim, para fazer a borda interna… (sabe como é, a pessoa responsável pelos layouts solta a criatividade e eu que me ferro)
      bom
      a segunda opção do post é legal demais e tudo. Porém, se eu der uns ‘br’ para descer a imagem, quando se passa o mouse no IE ele distorce, no FF fica beleza.
      Não tenho a mínima ideia de como resolver… o que eu fiz pra ter certeza, peguei o seu exemplo e copiei… pus uns enters e TCHAM! deu pau… rhehe
      vc tem idéia do que possa ser?

      Eu postei o exemplo aqui:
      http://sexsites.terra.com.br/sexboys/teste.html

      Se tiver alguma ideia pra me ajudar… eu agradeceria =D

      []’s

      Fabiano Carboni

    13. certo

      e como fazer para que apareca o centro da imagem e nao o canto superior esquerdo?
      vejo nas imagens da globo.com que o corte aproveita sempre o meio das imagens, as vezes corta um pedaco da cabeca mas fica otimo.

    14. nao entendi verissimo. eu expliquei nesse post exatamente como fazer o efeito da globo.com

    15. opa, mt bom seu post. achei um outro jeito bem facil de fazer borda interna tb aki nesse blog
      http://www.flog.co.nz/journal/inner-border/
      e é crossborowser.
      abraços

    16. era o que realmente eu tava procurando, eu vi esse lance no site da globo, e pesquisei na net, e o único lugar que achei um exemplo de como fazer bem o que eu queria foi aqui, legal gostei, dei uma lida por cima e esta bem didático,sou novo na área um estagiário praticamente, vou ver se consigo fazer isso aqui no trampo.Obrigado Dulcetti

    17. body {
      display:block;
      }

      div {
      width:600px;
      }

      div a {
      display:block;
      overflow:hidden;
      position:absolute;
      }

      div a:hover {
      border:3px solid #FF9900;
      }

      div a:hover img{
      display:block;
      margin:-3px;
      }

      Exemplo http://chutz.net/guigo/gornaldo.html

      Espero ter ajudado, abraços!

    18. ola
      na verdade consegui o que eu queria, cropar e usar o meio da imagem, da seguinte forma:

      * {margin:0;padding:0;}
      body {
      display:block;
      }

      div a {
      width:300px;
      height:200px;
      display:block;
      overflow:hidden;
      position:absolute;
      }

      div a:hover {
      border:3px solid #FF9900;
      }

      div img{
      margin-left:-100px;
      margin-top:-50px;
      }

      div a:hover img{
      margin-left:-103px;
      margin-top:-53px;
      display:block;
      }

      desvantaem
      a minha imagem esta no tamanho 500×300 por isso as margens foram calculadas previamente, no caso de uma imagem com tamanho diferente nao pegaria o centro da imagem.
      nesse caso todas as fotos teriam que vir no mesmo tamanho para dar certo

      teria uma solucao melhor trabalhando com style no local e usando php e para pegar o tamanho das imagens e calcular o espacametno necessario.

    19. HannibalGames | 18/ago/2009 às 3:45

      Cara era isso que eu queria tava procurando como botar a borda dentro da imagem… vlw mesmo agora sim ta igual o globo.com

    Tá esperando o quê? Comenta logo.

    
    Copyright © 2005 Bruno Dulcetti | Creative Commons
    Bruno Dulcetti atuante na área de desenvolvimento web / webdesign e colaborador na área de webstandards pelo Blog BrunoDulcetti.com - blog. Atuante na área desde 2000. Atuando na cidade de Niterói/RJ - Brasil. E-mail: bruno@brunodulcetti.com