質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.77%

特殊な形状に切り抜かれたストライプ背景の実装方法

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 862

aKusano

score 3705

やりたいこと

イメージ説明

↑こちらの画像のような一部が丸く飛び出した形になっている領域の背景をストライプで塗りつぶしたいのですが、
どのようにしたら切れ目なくストライプで塗りつぶせるか思いつきません。

条件

・ストライプ領域の上の部分は写真だったり、白背景だったりいろいろ。
・ストライプの領域の中は普通にテキストも含めたコンテンツが入るので幅・高さともに可変。
・丸く飛び出した領域の円形のサイズは固定。
・レスポンシブ

試したこと

四角いブロックの上に丸いブロックを重ねて、
それぞれの背景を-repeating-linear-gradient()でストライプに塗る

問題になっていること

四角い領域と丸い領域が別オブジェクトになっていると、どうしてもストライプがズレてしまう。
ストライプで塗りつぶされた領域がひとつの一体化した領域にできれば良いのでしょうが、
幅・高さが可変である状態でボックスの一部を丸く飛び出させる方法が思いつかない。

現状のコード(※簡易版)

実際にはもっと複雑なデザイン&コードなのですが、現在の実装方法と基本的に同じ考え方で
シンプルに再現した状態のコードを掲載しておきます。

<div class="block01"></div>
<div class="block02">
    <div class="circle"></div>
</div>    
* {margin: 0; padding: 0;}
.block01 {
    height: 200px;
    background: #f00;
}
.block02 {
    height: 200px;
    background: repeating-linear-gradient(to right, #d7f1fd 0, #d7f1fd 15px, #ebf8fe 15px, #ebf8fe 30px) center center;
}
.circle {
    position: relative;
    top: -40px;
    width: 100px;
    height: 100px;
    margin: 0 auto;
    border-radius: 50%;
    background: repeating-linear-gradient(to right, #d7f1fd 0, #d7f1fd 15px, #ebf8fe 15px, #ebf8fe 30px) center center;
}

何か良い方法はないでしょうか……?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • yasutomi

    2019/05/17 23:27

    肝心のあなたの試したコードが記載されていないです。

    キャンセル

  • aKusano

    2019/05/17 23:49

    簡易版のコードを掲載させていただきました。
    この方法だとブラウザ幅を変更する度に円の部分と四角の部分で
    ストライプがズレてしまうので、多分根本的に何か違う手法を考えないといけないのではないかな、と思っております。。。

    キャンセル

回答 5

+5

circle クラスを付与している要素の background-attachment プロパティ に対して fixed を設定することで、縞模様の切れ目がずれてしまう問題を解決することが出来ます。

上記の変更に加えて CSS を調整すると、質問者さんの実現したいことは以下のように行なえると思います(動作確認用リンク)。

<div class="block01"></div>
<div class="block02">
  <div class="circle"></div>
  <p>親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。弱虫やーい。と囃したからである。小使に負ぶさって帰って来た時、おやじが大きな眼をして二階ぐらいから飛び降りて腰を抜かす奴があるかと云ったから、この次は抜かさずに飛んで見せますと答えた。(青空文庫より)親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。弱虫やーい。と囃したからである。小使に負ぶさって帰って来た時、おやじが大きな眼をして二階ぐらいから飛び降りて腰を抜かす奴があるかと云ったから、この次は抜かさずに飛んで見せますと答えた。(青空文庫より)親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。弱虫やーい。と囃したからである。小使に負ぶさって帰って来た時、おやじが大きな眼をして二階ぐらいから飛び降りて腰を抜かす奴があるかと云ったから、この次は抜かさずに飛んで見せますと答えた。(青空文庫より)親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。弱虫やーい。と囃したからである。小使に負ぶさって帰って来た時、おやじが大きな眼をして二階ぐらいから飛び降りて腰を抜かす奴があるかと云ったから、この次は抜かさずに飛んで見せますと答えた。(青空文庫より)親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。弱虫やーい。と囃したからである。小使に負ぶさって帰って来た時、おやじが大きな眼をして二階ぐらいから飛び降りて腰を抜かす奴があるかと云ったから、この次は抜かさずに飛んで見せますと答えた。(青空文庫より)親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。弱虫やーい。と囃したからである。小使に負ぶさって帰って来た時、おやじが大きな眼をして二階ぐらいから飛び降りて腰を抜かす奴があるかと云ったから、この次は抜かさずに飛んで見せますと答えた。(青空文庫より)親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。弱虫やーい。と囃したからである。小使に負ぶさって帰って来た時、おやじが大きな眼をして二階ぐらいから飛び降りて腰を抜かす奴があるかと云ったから、この次は抜かさずに飛んで見せますと答えた。(青空文庫より)親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。弱虫やーい。と囃したからである。小使に負ぶさって帰って来た時、おやじが大きな眼をして二階ぐらいから飛び降りて腰を抜かす奴があるかと云ったから、この次は抜かさずに飛んで見せますと答えた。(青空文庫より)親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。弱虫やーい。と囃したからである。小使に負ぶさって帰って来た時、おやじが大きな眼をして二階ぐらいから飛び降りて腰を抜かす奴があるかと云ったから、この次は抜かさずに飛んで見せますと答えた。(青空文庫より)親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を抜かした事がある。なぜそんな無闇をしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談に、いくら威張っても、そこから飛び降りる事は出来まい。弱虫やーい。と囃したからである。小使に負ぶさって帰って来た時、おやじが大きな眼をして二階ぐらいから飛び降りて腰を抜かす奴があるかと云ったから、この次は抜かさずに飛んで見せますと答えた。(青空文庫より)親譲りの無鉄砲で小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰を</p>

</div>
* {
  margin: 0;
  padding: 0;
}

.block01 {
  height: 200px;
  background: #f00;
}

.block02 {
  min-height: 200px; /* 変更 */
  background: repeating-linear-gradient(
      to right,
      #d7f1fd 0,
      #d7f1fd 15px,
      #ebf8fe 15px,
      #ebf8fe 30px
    )
    center center;
}

.circle {
  position: relative;
  top: -40px;
  width: 100px;
  height: 100px;
  margin: 0 auto -100px; /* 変更 */
  border-radius: 50%;
  background: repeating-linear-gradient(
      to right,
      #d7f1fd 0,
      #d7f1fd 15px,
      #ebf8fe 15px,
      #ebf8fe 30px
    )
    center center fixed; /* 変更 */
}

.block02 > * {  /* 追記 */
  position: relative;
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/18 11:13 編集

    ご回答ありがとうございました!
    こんなシンプルな方法があったのですね!!!目からウロコです。
    が!残念ながらこの方法ではAndroid実機でズレたままになってしまいました。。
    IEでもうまくいったのに……orz
    コードもシンプルですし、ほんとうはベストアンサーにさせていただきたかったのですが
    Androidだけダメということと、yhgさんの方が先にご回答いただいていたということから
    残念ながら次点とさせていただきました。すみません。
    (気持ち的にはベストアンサーでも良いのですが一人にしかつけられないので…)

    キャンセル

  • 2019/05/18 18:32 編集

    解決されたようで良かったです。

    質問者さんが BA に選択したコードでは、スクロールバーの幅によって縞模様がずれてしまう場合がある ( https://codepen.io/anon/pen/gJRdwN ) ので、適宜 `scrollbar-width` プロパティを適用するか、 JavaScript でスクロールバーの幅分ずらす処理を行うなどの対応が必要だと思います。

    キャンセル

  • 2019/05/21 09:41

    おや!そうなんですか。。ちょっと調べてみますね!いろいろありがとうございます!!

    キャンセル

+3

力技。(左右にはみ出る物はうまく指定するか外側の要素で隠してください)

<div class="block01"></div>
<div class="block02">
    <div class="circle"></div>
    <div class="block03">a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s a s </div>
</div>    
.block02 {
    height: 200px;
}

.block03 {
  position: relative;
  top: -40px;
}

.circle {
    position: relative;
    width: 100px;
    height: 100px;
    margin: -40px auto 0;
    border-radius: 50%;
    background: repeating-linear-gradient(to right, #d7f1fd 0, #d7f1fd 15px, #ebf8fe 15px, #ebf8fe 30px) center center;
    background-image: linear-gradient(to right, #d7f1fd 0, #d7f1fd 15px, #ebf8fe 15px, #ebf8fe 30px);
    background-size: 30px;
    background-position-x: left;
}

.circle::before,
.circle::after {
    position: absolute;
    content: '';
    display: block;
    width: 52vw;
    height: 200vh;
    top: 40px;
    background-size: 30px;
    z-index: 0;
}

.circle::before {
  left: 30px;
    background-image: linear-gradient(to right, #d7f1fd 0, #d7f1fd 15px, #ebf8fe 15px, #ebf8fe 30px);
    background-position-x: left;
}

.circle::after {
  right: 25px;
    background-image: linear-gradient(to left, #d7f1fd 0, #d7f1fd 15px, #ebf8fe 15px, #ebf8fe 30px);
    background-position-x: right;
}

動くサンプル:https://jsfiddle.net/jzcw05ab/

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/18 01:10

    なるほどグラデーションを左右に付けるのですか。
    これは思いつかなかったです。
    (個人的にはこちらがベストアンサー)

    キャンセル

  • 2019/05/18 06:48

    s8_chuさんがbackground-attachment: fixed; を使用される方法を
    考案されていたので、現在ではあちらが個人的にはベストアンサー。

    キャンセル

  • 2019/05/18 11:09

    ご回答ありがとうございました。
    なるほどー、こういう考え方もあるんですね。。。
    サンプルの提示ではかなり省略してシンプルなコードにしましたが、
    実際の案件ではもうちょっと複雑でして、
    このやり方だとちょっと複雑になりすぎて大変そうだったので今回は見送らせていただきますが、
    今後の参考にさせていただきます!

    キャンセル

checkベストアンサー

+2

kei344様の案を見て思いついたのですが、
円部分にoverflow: hidden使いつつ、円の小要素を横座標0横幅100vwで配置し背景設定してみたら割とシンプルに実装できました。

<div class="block01"></div>
<div class="block02">
    <div class="circle"></div>
</div>
* {margin: 0; padding: 0;}
.block01 {
    height: 200px;
    background: #f00;
}
.block02 {
    position: relative;
    height: 200px;
    background: repeating-linear-gradient(to right, #d7f1fd 0, #d7f1fd 15px, #ebf8fe 15px, #ebf8fe 30px) center center;
}
.circle {
    width: 100px;
    height: 100px;
    margin: 0 auto;
    border-radius: 50%;
    transform: translateY(-40px); // transform すると position: relative を強制される
    overflow: hidden;
}
.circle::before {
    position: absolute;
    top: 0;
    left: calc(50px - 50vw); // 円の半径 - 50vw
    content: '';
    display: block;
    width: 100vw;
    height: 100%;
    background: repeating-linear-gradient(to right, #d7f1fd 0, #d7f1fd 15px, #ebf8fe 15px, #ebf8fe 30px) center center;
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/18 06:39

    私の方でも確認できました。
    // はCSSだとエラーなので /* */ に書き直した方が良いです。
    https://codepen.io/anon/pen/WBOZaK

    キャンセル

  • 2019/05/18 11:17

    ご回答ありがとうございました!
    今回はこちらのコードをベースに少し改変して採用させていただくことにしました!
    改変したところは以下の2点です。

    (1) .circleにposition:relativeを明記する
    コメントに、transformすると自動的にrelativeが適用されるとありましたが、
    Safariだと自動適用されないようでしたので手動でつける必要がありました。

    (2) repeating-linear-gradient()にbackground-attachment: fixedを追記
    上記コードだとIEでズレてしまったのでs8_chuさんのfixedをつける方法を追加しました。

    s8_chuさんの方法とyhgさんの方法をミックスさせるとすべての環境で思い通りの表示になる
    状態でしたので、どちらにベストアンサーをつけるべきか悩んだのですが、
    今回は先にご回答いただいたyhgさんをベストアンサーとさせていただきました。
    ありがとうございました。

    キャンセル

+2

興味あったので挑戦してみたところChromeではclip-pathで出来ました。

クロスブラウザ対応したい場合は Canvas 使うしかなさそうですね。

<section class="section">
  <div style="height:600px">
    hoge
  </div>
</section>
$circle-size: 128px;
$circle-offset-y: 16px;
$circle-height: ($circle-size / 2 - $circle-offset-y);

.section {
  position: relative;
  z-index: 0;
}

.section::before {
  content: '';
  display: block;
  height: $circle-height;
  width: 100%;
  clip-path: circle($circle-size at 50% $circle-size);
}

.section::after {
  content: '';
  display: block;
  position: absolute;
  top: $circle-height;
  left: 0;
  width: 100%;
  height: calc(100% - #{$circle-height});
}

.section::before,
.section::after {
  z-index: -1;
  background-color: rgb(226, 247, 255);
  background-image: repeating-linear-gradient(90deg, transparent, transparent 15px, rgb(207, 242, 255) 15px, rgb(207, 242, 255) 30px);
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/18 11:07

    ご回答ありがとうございます!
    今回はCSSだけでなんとかなりそうなのでCSSで対応することにいたしましたが、
    clip-pathで対応せざるを得ない場合の参考にさせていただきます!!

    キャンセル

+1

コードを見た限りでは全モダンブラウザで
そのような表示にする方法はおそらくないですね。

JavaScriptで.circleの位置を自動調整する方法は
CSSで位置情報を調整するという要望にお応えできませんし、少しずれます。

CSSのmaskプロパティやclip-pathを使用すれば可能ですが
未対応のブラウザがあるため現実的ではないです。
https://tech-dig.jp/css-mask/
https://developer.mozilla.org/ja/docs/Web/CSS/clip-path

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/18 00:16

    うーん、やっぱり今のやり方だと無理ですよねー。
    clip-pathを使う方法もちょっと考えたのですが、
    幅100%で円形の部分だけ固定でセンター配置にするようにclipするとか
    それはそれで無理っぽいように思えるのですが可能なんでしょうか…?

    キャンセル

  • 2019/05/18 01:02

    技術的には可能です。
    簡単に書くとこのようになります。
    https://codepen.io/anon/pen/KLqgNa

    キャンセル

  • 2019/05/18 11:05

    サンプルのご提示ありがとうございます!!
    今回はCSSだけでもなんとかなりそうなのでCSSで対応しますが、
    もう少し複雑な形状でクリップしなければならなくなったときの参考にさせていただきます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る