Wyrównaj dwa wbudowane bloki po lewej i prawej stronie w tej samej linii


113

Jak mogę wyrównać dwa bloki inline, tak aby jeden był po lewej, a drugi po prawej w tej samej linii? Dlaczego to takie trudne? Czy jest coś takiego jak \ hfill LaTeX-a, które może zająć przestrzeń między nimi, aby to osiągnąć?

Nie chcę używać pływaków, ponieważ dzięki blokom inline mogę wyrównać linie bazowe. A kiedy okno jest za małe dla nich obu, za pomocą bloków inline mogę po prostu zmienić wyrównanie tekstu na środek, a zostaną wyśrodkowane jeden na drugim. Pozycjonowanie względne (nadrzędne) + bezwzględne (element) ma te same problemy, co elementy zmiennoprzecinkowe.

HTML5:

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

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

Są tuż obok siebie, ale ja chcę navpo prawej stronie.

diagram


1
AFAIK jedynym sposobem rozwiązania tego problemu jest użycie wartości zmiennoprzecinkowych lub pozycjonowania bezwzględnego. Możesz osiągnąć tę samą pozycję bazową, używając górnej krawędzi marginesu na panelu nawigacyjnym.
powerbuoy

Po prostu użyj marginesów i pływaków. Nie można tego zrobić bez tego lub pozycjonowania absolutnego.
jdhartley

Użyj zapytań o media css, aby zmienić css w zależności od rozmiaru widocznego obszaru. Możesz użyć obu position: absoluteiinline-block
elclanrs

Odpowiedzi:


147

Edycja: minęły 3 lata odkąd odpowiedziałem na to pytanie i myślę, że potrzebne jest bardziej nowoczesne rozwiązanie, chociaż obecne robi to :)

1. Flexbox

To zdecydowanie najkrótszy i najbardziej elastyczny. Zastosuj display: flex;do kontenera nadrzędnego i dostosuj położenie jego elementów podrzędnych w justify-content: space-between;następujący sposób:

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

Można go zobaczyć online tutaj - http://jsfiddle.net/skip405/NfeVh/1073/

Należy jednak pamiętać, że obsługa flexbox to IE10 i nowsze. Jeśli potrzebujesz obsługi przeglądarki IE 9 lub starszej, użyj następującego rozwiązania:

2. Możesz użyć tej text-align: justifytechniki tutaj.

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

Działający przykład można zobaczyć tutaj: http://jsfiddle.net/skip405/NfeVh/4/ . Ten kod działa od IE7 i nowszych

Jeśli elementy inline-block w HTML nie są oddzielone spacjami, to rozwiązanie nie zadziała - zobacz przykład http://jsfiddle.net/NfeVh/1408/ . Może tak być w przypadku wstawiania treści za pomocą JavaScript.

Jeśli nie obchodzi nas IE7, po prostu pomiń właściwości star-hack. Działający przykład wykorzystujący twoje znaczniki jest tutaj - http://jsfiddle.net/skip405/NfeVh/5/ . Właśnie dodałem header:afterczęść i uzasadniłem treść.

W celu rozwiązania problemu dodatkowej przestrzeni wstawianej z afterpseudoelementem można wykonać sztuczkę polegającą na ustawieniu wartości font-size0 dla elementu nadrzędnego i zresetowaniu go z powrotem do 14 pikseli dla elementów potomnych. Działający przykład tej sztuczki można zobaczyć tutaj: http://jsfiddle.net/skip405/NfeVh/326/


1
Czy jest jakiś sposób, aby powstrzymać go przed podwyższeniem banera? Zdaję sobie sprawę, jak to działa, więc zakładam, że tak nie jest.
mk12

1
Jeśli generujesz zawartość za pomocą javascript, pamiętaj, że to rozwiązanie działa tylko wtedy, gdy między elementami są spacje. Będziesz musiał wstawić węzeł tekstowy między lewy / prawy element lub oba będą trzymane po lewej stronie.
Stephen Nelson

1
Czy mógłbyś również wkleić tutaj swój kod? Linki do zewnętrznych miejsc mają w zwyczaju umierać w pewnym momencie, a jeśli tak się stanie, ta użyteczna odpowiedź nagle stanie się bezużyteczna.
LUB Mapper

5
@ ValerioColtrè Zgadzam się, że pusta przestrzeń jest najbardziej (i prawdopodobnie jedyną!) Irytującą rzeczą w tym podejściu. Jawne zarządzanie swoim font-sizejest raczej niepożądane. Proponuję inne rozwiązanie. Zauważ, że .header:afterdekorator dodaje jedną linię o wysokości równej font-size. Na szczęście wiemy, ile to kosztuje. To jest dokładnie 1em! A więc ujemne marże na ratunek! To skrzypce pokazuje, jak to zrobić .
Domi

1
@ skip405 Uwaga: ustawienie wysokości linii na 0 w elemencie opakowującym (nagłówku) i naprawienie wyrównania w pionie jego pseudoelem (powiedzmy vertical-align: top) może rozwiązać problem dodatkowej przestrzeni. Oczywiście musimy ponownie ustawić wysokość linii w elementach nadrzędnych, ale w wielu przypadkach może to być łatwiejsze. jsfiddle.net/bencergazda/3gL8153n/7
bencergazda

5

Korzystając z odpowiedzi @ skip405, stworzyłem dla niej mixin Sass:

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

Przyjmuje 3 parametry. Kontener, lewy i prawy element. Na przykład, aby dopasować pytanie, możesz użyć tego w następujący sposób:

@include inline-block-lr('header', 'h1', 'nav');

3

Jeśli nie chcesz używać pływaków, będziesz musiał zawinąć swoją nawigację:

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

... i dodaj bardziej szczegółowe css:

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

Być może będziesz musiał zrobić trochę więcej, ale to początek.


1

Jeśli już używasz JavaScript do wyśrodkowania rzeczy, gdy ekran jest zbyt mały (zgodnie z komentarzem do twojego nagłówka), dlaczego nie cofnąć ruchów / marginesów za pomocą JavaScript, gdy jesteś przy tym i normalnie używaj pływaków i marginesów.

Możesz nawet użyć zapytań o media CSS, aby zmniejszyć ilość używanego kodu JavaScript.


Chyba jeszcze o tym nie myślałem, po prostu wydawało mi się, że w ten sposób będzie łatwiej. Ale najwyraźniej nie. Jakieś wskazówki, jak podłączyć się do nawigacji przechodząc do następnej linii z javascript?
mk12

Ach, mogę w tym celu użyć zapytań o media! Myślałem, że te były używane tylko podczas uruchamiania, a nie podczas zmiany rozmiaru. Dzięki.
mk12

1

Myślę, że jednym z możliwych rozwiązań jest użycie 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/



0

Wyświetlanie lewej środkowej i prawej strony rodziców. Jeśli masz więcej niż 3 elementy, użyj dla nich nth-child ().

wprowadź opis obrazu tutaj

Przykład 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>

Przykład 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%);
}

-1

daj mu float: right i h1 float: left i wstaw element z clear: oba po nich.


8
Nie chcę używać pływaków
powerbuoy

@powerbuoy zabawne, że wybrał rozwiązanie z pływakami na końcu, prawda?
Itay Moav -Malimovka

@Włochy: Tylko dlatego, że myślałem, że to jedyny możliwy sposób - zmieniłem zaakceptowaną odpowiedź.
mk12

-1

Do obu elementów użyj

display: inline-block;

do użycia elementu „nav”

float: right;

2
W przypadku pływaka nie można stosować zawijania.
Ievgen Naida
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.