Alinha dois blocos embutidos à esquerda e à direita na mesma linha

113

Como posso alinhar dois blocos embutidos de modo que um fique à esquerda e o outro à direita na mesma linha? Por que isso é tão difícil? Existe algo como o \ hfill do LaTeX que pode consumir o espaço entre eles para conseguir isso?

Não quero usar flutuadores porque com blocos embutidos posso alinhar as linhas de base. E quando a janela é muito pequena para ambos, com blocos embutidos, posso apenas alterar o alinhamento do texto para o centro e eles serão centralizados um sobre o outro. O posicionamento relativo (pai) + absoluto (elemento) tem os mesmos problemas que os flutuadores.

O HTML5:

<header>
    <h1>Title</h1>
    <nav>
        <a>A Link</a>
        <a>Another Link</a>
        <a>A Third Link</a>
    </nav>
</header>

O css:

header {
    //text-align: center; // will set in js when the nav overflows (i think)
}

h1 {
    display: inline-block;
    margin-top: 0.321em;
}

nav {
    display: inline-block;
    vertical-align: baseline;
}

Estão bem próximos um do outro, mas eu quero do navlado direito.

um diagrama

mk12
fonte
1
AFAIK, a única maneira de resolver isso é usar flutuadores ou posicionamento absoluto. Você pode obter a mesma posição da linha de base usando a margem superior no navegador.
powerbuoy de
Basta usar margem superior e flutuadores. Não é possível fazer isso sem isso ou posicionamento absoluto.
jdhartley
Use css media queries para alterar o css dependendo do tamanho da janela de visualização. Você pode usar ambos position: absoluteeinline-block
elclanrs de

Respostas:

147

Edit: 3 anos se passaram desde que eu respondi a esta pergunta e eu acho que uma solução mais moderna é necessária, embora a atual faça a coisa :)

1. Flexbox

É de longe o mais curto e flexível. Aplique display: flex;ao contêiner pai e ajuste o posicionamento de seus filhos da justify-content: space-between;seguinte maneira:

.header {
    display: flex;
    justify-content: space-between;
}

Pode ser visto online aqui - http://jsfiddle.net/skip405/NfeVh/1073/

Observe, entretanto, que o suporte a flexbox é o IE10 e mais recente. Se você precisar oferecer suporte ao IE 9 ou mais antigo, use a seguinte solução:

2. Você pode usar a text-align: justifytécnica aqui.

.header {
    background: #ccc; 
    text-align: justify; 

    /* ie 7*/  
    *width: 100%;  
    *-ms-text-justify: distribute-all-lines;
    *text-justify: distribute-all-lines;
}
 .header:after{
    content: '';
    display: inline-block;
    width: 100%;
    height: 0;
    font-size:0;
    line-height:0;
}

h1 {
    display: inline-block;
    margin-top: 0.321em; 

    /* ie 7*/ 
    *display: inline;
    *zoom: 1;
    *text-align: left; 
}

.nav {
    display: inline-block;
    vertical-align: baseline; 

    /* ie 7*/
    *display: inline;
    *zoom:1;
    *text-align: right;
}

O exemplo de trabalho pode ser visto aqui: http://jsfiddle.net/skip405/NfeVh/4/ . Este código funciona a partir do IE7 e superior

Se os elementos do bloco embutido em HTML não forem separados por espaço, esta solução não funcionará - veja o exemplo http://jsfiddle.net/NfeVh/1408/ . Este pode ser o caso quando você insere conteúdo com Javascript.

Se não nos importamos com o IE7, simplesmente omita as propriedades star-hack. O exemplo de trabalho usando sua marcação está aqui - http://jsfiddle.net/skip405/NfeVh/5/ . Eu apenas adicionei a header:afterparte e justifiquei o conteúdo.

Para resolver o problema do espaço extra que é inserido com o afterpseudoelemento, pode-se fazer um truque para definir o font-sizecomo 0 para o elemento pai e redefini-lo para, digamos, 14 px para os elementos filhos. O exemplo prático desse truque pode ser visto aqui: http://jsfiddle.net/skip405/NfeVh/326/

skip405
fonte
1
Existe alguma maneira de impedir que o banner fique mais alto? Sei como isso está funcionando, então presumo que não.
mk12
1
Se você estiver gerando seu conteúdo com javascript, observe que esta solução só funciona se houver espaço em branco entre os elementos. Você precisará inserir um nó de texto entre os elementos esquerdo / direito ou ambos ficarão à esquerda.
Stephen Nelson
1
Você se importaria de colar seu código aqui também? Links para lugares externos têm o hábito de morrer em algum ponto e, se isso acontecer, essa resposta útil de repente se tornará inútil.
OR Mapper
5
@ ValerioColtrè Concordo que o espaço vazio é a coisa mais (e possivelmente, a única!) Chata nesta abordagem. Gerenciar explicitamente o seu font-sizeé bastante indesejável. Eu proponho uma solução diferente. Observe que o .header:afterdecorador adiciona uma linha de altura igual a font-size. Felizmente, sabemos quanto isso é. É exatamente isso 1em! Portanto, margens negativas para o resgate! Este violino mostra como .
Domi,
1
@ skip405 Nota: definir a altura da linha para 0 no elemento de invólucro (cabeçalho) e corrigir o alinhamento vertical de seu pseudo-elemento (alinhamento vertical: topo, digamos) pode corrigir o problema de espaço extra. É claro que temos que redefinir a altura da linha nos elementos pais, mas pode ser mais fácil em muitos casos. jsfiddle.net/bencergazda/3gL8153n/7
bencergazda
5

Aproveitando a resposta de @ skip405, fiz um mixin Sass para ele:

@mixin inline-block-lr($container,$left,$right){
    #{$container}{        
        text-align: justify; 

        &:after{
            content: '';
            display: inline-block;
            width: 100%;
            height: 0;
            font-size:0;
            line-height:0;
        }
    }

    #{$left} {
        display: inline-block;
        vertical-align: middle; 
    }

    #{$right} {
        display: inline-block;
        vertical-align: middle; 
    }
}

Aceita 3 parâmetros. O contêiner, o elemento esquerdo e o direito. Por exemplo, para responder à pergunta, você poderia usá-lo assim:

@include inline-block-lr('header', 'h1', 'nav');
Pablo SG Pacheco
fonte
3

Se você não quiser usar flutuadores, terá que embrulhar seu nav:

<header>
<h1>Title</h1>
<div id="navWrap">
<nav>
    <a>A Link</a>
    <a>Another Link</a>
    <a>A Third Link</a>
</nav>
</div>
</header>

... e adicione alguns css mais específicos:

header {
//text-align: center; // will set in js when the nav overflows (i think)
width:960px;/*Change as needed*/
height:75px;/*Change as needed*/
}

h1 {
display: inline-block;
margin-top: 0.321em;
}

#navWrap{
position:absolute;
top:50px; /*Change as needed*/
right:0;
}

nav {
display: inline-block;
vertical-align: baseline;
}

Você pode precisar fazer um pouco mais, mas isso é um começo.

maiorano84
fonte
1

Se você já está usando JavaScript para centralizar coisas quando a tela é muito pequena (de acordo com seu comentário para o cabeçalho), por que não apenas desfazer flutuações / margens com JavaScript enquanto você está nisso e usar flutuações e margens normalmente.

Você pode até usar consultas de mídia CSS para reduzir a quantidade de JavaScript que está usando.

Jdhartley
fonte
Acho que ainda não estava pensando sobre isso, apenas parecia que seria mais fácil dessa forma. Mas aparentemente não. Alguma dica de como eu conectaria o navegador saltando para a próxima linha do javascript?
mk12,
Ahh, posso usar consultas de mídia para isso! Achei que eles só fossem usados ​​na inicialização, não no redimensionamento. Obrigado.
mk12,
1

Acho que uma solução possível para isso é usar display: table:

.header {
  display: table;
  width: 100%;
  box-sizing: border-box;
}

.header > * {
  display: table-cell;
}

.header > *:last-child {
  text-align: right;  
}

h1 {
  font-size: 32px;
}

nav {
  vertical-align: baseline;
}

JSFiddle: http://jsfiddle.net/yxxrnn7j/1/

roubo
fonte
0

Novas maneiras de alinhar os itens da maneira certa:

Grade :

.header {
        display:grid;
        grid-template-columns: 1fr auto;
    }

Demo

Bootstrap 4. Alinhar à direita :

<div class="row">
      <div class="col">left</div>
      <div class="col">
          <div class="float-right">element needs to be right aligned</div>
      </div>
</div>

Demo

Ievgen Naida
fonte
0

Exibindo meio esquerdo e direito de seus pais. Se você tiver mais de 3 elementos, use nth-child () para eles.

insira a descrição da imagem aqui

Amostra de HTML:

<body>
    <ul class="nav-tabs">
        <li><a  id="btn-tab-business" class="btn-tab nav-tab-selected"  onclick="openTab('business','btn-tab-business')"><i class="fas fa-th"></i>Business</a></li>
        <li><a  id="btn-tab-expertise" class="btn-tab" onclick="openTab('expertise', 'btn-tab-expertise')"><i class="fas fa-th"></i>Expertise</a></li>
        <li><a  id="btn-tab-quality" class="btn-tab" onclick="openTab('quality', 'btn-tab-quality')"><i class="fas fa-th"></i>Quality</a></li>
    </ul>
</body>

Amostra CSS:

.nav-tabs{
  position: relative;
  padding-bottom: 50px;
}

.nav-tabs li {
  display: inline-block;  
  position: absolute;
  list-style: none;
}
.nav-tabs li:first-child{
  top: 0px;
  left: 0px;
}
.nav-tabs li:last-child{
  top: 0px;
  right: 0px;
}
.nav-tabs li:nth-child(2){
  top: 0px;
  left: 50%;
  transform: translate(-50%, 0%);
}
senhor
fonte
-1

dê a ele float: right e h1 float: left e coloque um elemento com clear: ambos após eles.

Itay Moav -Malimovka
fonte
8
" Eu não quero usar flutuadores "
powerbuoy de
@powerbuoy engraçado ele selecionou a solução com flutuadores no final, certo?
Itay Moav -Malimovka
@Itália: Só porque pensei que era a única maneira possível - mudei minha resposta aceita.
mk12
-1

Para ambos os elementos, use

display: inline-block;

o para o uso do elemento 'nav'

float: right;
Sammy Aguns
fonte
2
Para um float, nenhum envoltório pode ser usado.
Ievgen Naida