Jak sprawić, by zaokrąglone rogi CSS3 ukryły przepełnienie w Chrome / Opera

147

Potrzebuję zaokrąglonych rogów nadrzędnego elementu DIV, aby zamaskować zawartość przed jego potomkiem. overflow: hiddendziała w prostych sytuacjach, ale psuje się w przeglądarkach opartych na webkitach i Operze, gdy rodzic jest ustawiony względnie lub absolutnie.

Działa to w przeglądarce Firefox i IE9:

CSS

#wrapper {
  width: 300px;
  height: 300px;
  border-radius: 100px;
  overflow: hidden;
  position: absolute;
}

#box {
  width: 300px;
  height: 300px;
  background-color: #cde;
}

HTML

<div id="wrapper">
  <div id="box"></div>
</div>

Przykład na JSFiddle

Dzięki za pomoc!

AKTUALIZACJA: błąd powodujący ten problem został już naprawiony w Chrome. Nie testowałem jednak ponownie Opery ani Safari.

jmotes
źródło

Odpowiedzi:

183

Znalazłem inne rozwiązanie tego problemu. Wygląda to na kolejny błąd w WebKit (lub prawdopodobnie w Chrome), ale działa. Wszystko, co musisz zrobić - to dodać maskę CSS WebKit do elementu #wrapper. Możesz użyć pojedynczego piksela png, a nawet dołączyć go do CSS, aby zapisać żądanie HTTP.

#wrapper {
width: 300px; height: 300px;
border-radius: 100px;
overflow: hidden;
position: absolute; /* this breaks the overflow:hidden in Chrome/Opera */

/* this fixes the overflow:hidden in Chrome */
-webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);
}

#box {
width: 300px; height: 300px;
background-color: #cde;
}​

Przykład JSFiddle

graycrow
źródło
3
dziękuję za tę poprawkę. wypróbowałem to dzisiaj na safari (wersja 6.0.2) i tam dla mnie zadziałało!
Billythetalentowany
6
to jednak usunie wszelkie cienie na elemencie.
Jack James
1
Działa to również na opakowaniach z pozycjami dziećmi pozycjonowanymi absolutnie, gdzie inne rozwiązanie tutaj nie działa. Miły!
Dan Tello
2
przy użyciu przeglądarki Chrome 42.0.2311.90 (64-bitowej), a ta poprawka jest nadal wymagana ... dzięki!
simon
2
Twoje rozwiązania usuwają cienie elementu macierzystego.
ABDeveloper
106

Dodaj indeks Z do elementu z border-radius, a zamaskuje on rzeczy w nim zawarte.

Jackolai
źródło
@Sifu: po prostu się mylisz. Z jakiegoś powodu dodanie indeksu z zgodnie z sugestią rozwiązało dokładnie ten problem (w obecnej wersji Chrome) i jest to prostsze, bardziej ogólne rozwiązanie niż najlepsza odpowiedź.
Nick F
7
@simon: pamiętaj, że aby indeks z działał, muszą być spełnione określone warunki (np. należy ustawić pozycję). Zobacz tutaj o szczegóły.
Nick F
@NickF - to był błąd w Chrome (-ium); -webkit-mask-image: -webkit-radial-gradient(circle, white, black);było skutecznym obejściem, ale na szczęście błąd został naprawiony w ostatniej aktualizacji Chrome, którą otrzymałem.
simon
Z-index 1 do kontenera. z-index -1 do elementu absolutnego rozwiązało to za mnie.
aZtraL-EnForceR
Ten pracował dla mnie. Powyższe rozwiązanie opakowujące nie.
Ruwen
58

Nieważne dla wszystkich, udało mi się rozwiązać problem, dodając dodatkowy element div między opakowaniem a pudełkiem.

CSS

#wrapper {
    position: absolute;
}

#middle {
    border-radius: 100px;
    overflow: hidden; 
}

#box {
    width: 300px; height: 300px;
    background-color: #cde;
}

HTML

<div id="wrapper">
    <div id="middle">
        <div id="box"></div>
    </div>
</div>

Dziękuję wszystkim, którzy pomogli!

http://jsfiddle.net/5fwjp/

jmotes
źródło
12
To działa, ponieważ pozycjonowane elementy nie przycinają swojej zawartości do swojego border-radius w Webkicie. Ta dodatkowa warstwa po prostu sprawia, że ​​element div z border-radius NIE jest ustawiony i po prostu znajduje się wewnątrz pozycjonowanego elementu.
Daniel Beardsley,
9
Czy przypadkiem wiesz, czy jest to błąd / zamierzone zachowanie?
jmotes
4
+1 głos na błąd ... Jeśli masz galerię obrazów, która automatycznie generuje elementy div i ustawia pozycję na wartość bezwzględną, to ta "funkcja" naprawdę sux ...
inf3rno
@RunLoop Właśnie przetestowałem jsfiddle w Safari 7.1 i działa dobrze. Czy możesz bardziej szczegółowo określić, co nie działa?
jmotes
1
Nasz kolega, grafik, faktycznie "odkrył" to 20 sekund przed znalezieniem takiej odpowiedzi: D
Pere
18

krycie: 0,99; na opakowaniu rozwiązuje błąd webkita

flavi1
źródło
2
transform: translateY(0);to alternatywa, która daje ten sam rezultat bez ingerencji w wizualną reprezentację obiektu (chyba że używasz perspektywy).
kontur,
15

Wygląda na to, że ten działa:

.wrap {
    -webkit-transform: translateZ(0);
    -webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%);
}

http://jsfiddle.net/qWdf6/82/

nakrill
źródło
4
transform: translateZ(0)mi wystarczy.
kalvn
Zauważ, że to (w szczególności translateZ) pośrednio włączy przyspieszenie sprzętowe dla twoich elementów, co niestety otwiera zupełnie nową puszkę robaków w niektórych przypadkach.
doldt
transform: translateZ(0)również pracował dla mnie. W moim przypadku nie jest złym pomysłem, że ten element jest akcelerowany sprzętowo.
Sebastien Lorber
9

Obsługiwane w najnowszym Chrome, Opera i Safari, możesz to zrobić:

-webkit-clip-path: inset(0 0 0 0 round 100px);
clip-path: inset(0 0 0 0 round 100px);

Zdecydowanie powinieneś sprawdzić narzędzie http://bennettfeely.com/clippy/ !

antoni
źródło
Myślę, że możesz skrócić tę ścieżkę przycinania jeszcze bardziej : wstawka (0%); ... sama ścieżka klipu wydaje się działać :-)
Jakob E
Łał. To doskonała odpowiedź.
Shashank Bhatt
4

zmień krycie elementu nadrzędnego za pomocą obramowania, co spowoduje zmianę organizacji ułożonych w stos elementów. To zadziałało cudownie po wielu godzinach poszukiwań i nieudanych próbach. Było to tak proste, jak dodanie krycia 0,99 w celu ponownego zorganizowania procesu malowania przeglądarek. Sprawdź http://philipwalton.com/articles/what-no-one-told-you-about-z-index/

Rami Awar
źródło
3

Jak dla mnie żadne z rozwiązań nie działało dobrze, tylko przy użyciu:

-webkit-mask-image: -webkit-radial-gradient(circle, white, black);

element opakowania wykonał zadanie.

Tutaj przykład: http://jsfiddle.net/gpawlik/qWdf6/74/

Grzegorz Pawlik
źródło
2

w oparciu o doskonałą odpowiedź Graycrow ...

Oto bardziej realny przykład, w którym znajdują się dwa cykliczne elementy DIV z pewną zawartością wypełniacza. Zastąpiłem zakodowane na stałe tło png tylko wartością szesnastkową, tj

-=-webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);

jest zastępowany przez

-webkit-mask-image:#fff;

Zobacz ten JSFiddle ... http://jsfiddle.net/hqLkA/

gts101
źródło
1

Zobacz, jak to zrobiłem; Jsfiddle

Dzięki kodowi, który wstawiłem, udało mi się uruchomić go na Webkit (Chrome / Safari) i Firefox. Nie wiem, czy działa z najnowszą wersją Opery. Tak, działa w najnowszej wersji Opery.

#wrapper {
  width: 300px; height: 300px;
  border-radius: 100px;
  overflow: hidden;
  position: absolute; /* this breaks the overflow:hidden in Chrome/Opera */
}

#box {
  width: 300px; height: 300px;
  background-color: #cde;
  border-radius: 100px;
  -webkit-border-radius: 100px;
  -moz-border-radius: 100px;
  -o-border-radius: 100px;
}
Labirynt
źródło
Po co border-radiusw ogóle zawracać sobie głowę zakładaniem opakowania na opakowanie w takiej sytuacji, ten sam rezultat można uzyskać, ustawiając go po prostu #box. Ponadto, jeśli #boxpromień obramowania służy tylko do naprawienia WebKita, możesz po prostu dołączyć -webkit-tam właściwość.
robertc
Labirynt, może to zadziałać w niektórych sytuacjach, ale w moim przypadku szukam rozwiązania, które nie zmienia kształtu pudełka (a opakowanie nadal działa jak maska). Mój przykład był bardzo uproszczony, ale próbuję użyć opakowania, aby ukryć cień z pudełka (używając wypełnienia na opakowaniu, aby widoczne były tylko krawędzie cienia, które chcę).
jmotes
1
Dzięki za pomoc przez Maze! Twoje rozwiązanie pomogło mi bardziej krytycznie spojrzeć na problem. Przy okazji, możesz zignorować zmianę, którą wprowadziłem w swoim poście. Chciałem zrobić to dla siebie. Przepraszam :)
jmotes
@ user480837 Żaden problem kolego, cieszę się, że pomogłem. :)
Maze
1
@Maze To nie zadziała, jeśli zostanie zastosowana jakakolwiek ramka
antitoxic
1

Próbowałem każdej odpowiedzi, ale bezskutecznie. Po kilku godzinach badania znalazłem rozwiązanie tego problemu. Użycie tych właściwości w Twojej klasie nie pozwoli elementom div na przepełnienie kontenera.

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
}
Samin
źródło
0

Jeśli chcesz utworzyć maskę dla obrazu i umieścić obraz w kontenerze, nie ustawiaj atrybutu „pozycja: absolutna”. Wszystko, co musisz zrobić, to zmienić margines lewy i prawy margines. Chrome / Opera będzie przestrzegać przepełnienia: reguł ukrytych i obramowań.

// Breaks in Chrome/Opera.
    .container {
        overflow: hidden;
        border-radius: 50%;
        img {
            position: absolute;
            left: 20px;
            right: 20px;
        }
    }

// Works in Chrome/Opera.
    .container {
        overflow: hidden;
        border-radius: 50%;
        img {
            margin-left: 20px;
            margin-right: 20px;
        }
    }
user6039997
źródło