CSS 미디어 쿼리-소프트 키보드가 CSS 방향 규칙을 위반 함-대체 솔루션?


84

여러 태블릿 장치를 사용하고 있습니다-둘 다 Android 및 iOS. 현재 모든 태블릿에 대해 다음과 같은 해상도 변형이 있습니다.

  • 1280 x 800
  • 1280 x 768
  • 1024 x 768 (당연히 iPad) -iPad에는이 문제가 없습니다.

장치 방향 기반 스타일을 적용하는 가장 간단한 방법은 다음 구문을 사용하여 미디어 쿼리의 방향을 사용하는 것입니다.

@media all and (orientation:portrait)
{
  /* My portrait based CSS here */
}

@media all and (orientation:landscape)
{
  /* My landscape based CSS here */
}

이것은 모든 태블릿 장치에서 완벽하게 작동합니다. 그러나 문제는 장치가 세로 모드이고 사용자가 입력 필드 (예 : 검색)를 탭하면 소프트 키보드가 팝업되어 웹 페이지의 가시 영역을 줄이고 가로 기반 CSS로 렌더링하도록 강제하는 것입니다. 안드로이드 태블릿 기기에서는 키보드 높이에 따라 다릅니다. 따라서 궁극적으로 웹 페이지가 깨져 보입니다. 따라서 CSS3의 방향 미디어 쿼리를 사용하여 방향에 따라 스타일을 적용 할 수 없습니다 (대상 방향에 더 나은 미디어 쿼리가없는 경우). 다음은 이것을 에뮬레이트 하는 바이올린 http://jsfiddle.net/hossain/S5nYP/5/ 입니다-장치 테스트의 경우 전체 테스트 페이지 사용 -http : //jsfiddle.net/S5nYP/embedded/result/

다음은 데모 페이지에서 가져온 동작의 스크린 샷입니다. 여기에 이미지 설명 입력

따라서이 문제를 해결할 수있는 대안이 있습니까? 네이티브 CSS 기반 솔루션이 작동하지 않는 경우 JavaScript 기반 솔루션에 개방되어 있습니다.

http://davidbcalhoun.com/2010/dealing-with-device-orientation에서 클래스를 추가하고이를 기반으로 타겟팅 할 것을 제안 하는 스 니펫을 찾았습니다 . 예를 들면 :

<html class="landscape">
  <body>
    <h1 class="landscape-only">Element Heading - Landscape</h1>
    <h1 class="portrait-only">Element Heading - Portrait</h1>
    <!-- .... more... ->

# CSS
.landscape .landscape-only { display:block; }
.landspace .portrait-only  { display:none; }
.portrait .portrait-only   { display:block; }
.portrait .landscape-only  { display:none; }

너희들은 이것에 대해 어떻게 생각하니? 더 나은 솔루션이 있습니까?


방금 알게 된 것은 iPad 에는이 문제 가 없습니다 . Android OS (벌집 태블릿) 및 모바일에만이 문제가 있습니다.
Hossain Khan

내 모바일 웹 사이트에서 비슷한 문제가 발생했습니다. 몇 개의 Android 기기에서 테스트 한 후 특정 OS 또는 모바일 / 태블릿 기기로 제한되지 않는 것 같습니다. 주로 Motorola 및 Samsung 장치의 문제인 것 같습니다. HTC 휴대 전화에서 문제를 재현 할 수 없습니다.
TJ Kirchner 2012 년

1
이 문제는 주로 Android 기기, 모바일 / 태블릿에서 발생합니다.이 문제를 재현 할 수있는 유일한 방법은 높이가 큰 사용자 지정 키보드를 설치하는 것이므로 키보드가 표시 될 때 webview에 사용 가능한 높이가 사용 가능한 너비보다 작습니다. 그래야만 webview가 방향 변경을 트리거합니다. 예를 들어 스크린 샷에서 키보드 상단의 제안 레이어를 비활성화 할 수 있다면 웹뷰 높이가 너비보다 크기 때문에이 문제가 발생하지 않습니다. 그러나 어쨌든 우아하고 효율적인 솔루션이 아직 없습니다.
Hossain Khan

1
그냥 IOS 7.0.0 전체 화면 웹 애플리케이션도이 동작을하고 있다는 것을 깨닫게
알렉상드르

그거 슬프다. 문제를 효율적으로 해결할 수 없어서 known limitation.
Hossain Khan

답변:


105

나는 이것이 몇 년 늦었지만 훌륭한 해결책을 찾았습니다.

가로 미디어의 경우 :

@media screen and (min-aspect-ratio: 13/9) { /* landscape styles here */}

세로 미디어의 경우 :

@media screen and (max-aspect-ratio: 13/9) { /* portrait styles here */}

전체 솔루션과 작동 이유는 여기에서 찾을 수 있습니다. Michael Barret-Android 브라우저 문제

편집 :이 링크는 현재 만료되었지만 인터넷 아카이브에서 스냅 샷을 찾을 수 있습니다. Michael Barret-Android 브라우저 문제


2
이 문제를 해결하지만, 나를 위해 다른 장치에 대한 문제 (주로 노트북과 컴퓨터) 생성
스테판 Bijzitter

불행히도이 솔루션은 모든 모바일 장치에서 작동하지 않습니다.
Diogo Cardoso

@StephanBijzitter 아마도 'max-width'속성을 사용할 수 있습니까?
Sean Routledge 2015

3
이 솔루션은 매우 거칠고 일부 장치에서는 작동하지 않습니다. 예를 들어 내 휴대 전화는 소프트 키보드를 열 때 약 17.7 / 9를 제공하지만 다른 많은 기기에서는 가로 화면 비율이 훨씬 적습니다.
raacer

2
전체 솔루션 링크가 끊어졌습니다.
Sparkmorry

27

문제는 방향이 계산되는 방식에 있습니다.

http://www.w3.org/TR/css3-mediaqueries/#orientation

'방향'미디어 기능은 '높이'미디어 기능의 값이 '너비'미디어 기능의 값보다 크거나 같을 때 '세로'입니다. 그렇지 않으면 '방향'은 '가로'입니다.

높이 / 너비가 보이는 뷰포트에서 계산되기 때문에 소프트 키보드는 뷰포트 너비가 높이보다 작기 때문에 방향을 뒤집는 것으로 보입니다. 한 가지 해결책은 width대신에 기반한 미디어 쿼리를 사용하는 것입니다. 따라서 너비 / 높이가 방향보다 더 광범위하게 지원된다는 점은 말할 것도없고 방향에 관계없이 여러 장치에서 더 유연하게 사용할 수 있습니다.

방향 대신 너비를 고려하고 싶다면 iPhone을 예로 들어 보겠습니다.

@media screen and (max-width: 320px) {
  /* rules applying to portrait */
}

@media screen and (max-width: 480px) {
  /* rules applying to landscape */
}

이 접근 방식은 방향 이 너비에 비해 거의 알려주는 것은 말할 것도없고 방향을 지원하는 장치 / 사용자 에이전트로 쿼리가 제한되지 않기 때문에 방향보다 더 유연 합니다.

물론 오리엔테이션 을 정말로 알아야 한다면 처음에 수업을 설정하는 것처럼 보이며 최선의 선택이 될 수 있습니다.


1
브라우저에서 가로와 세로가 어떻게 계산되는지 이해합니다. 그러나 이것을 처리하는 대안과 더 나은 방법이 필요합니다. 또 다른 흥미로운 점은 iPad가 키보드가 올라갈 때 방향 변경을 트리거하지 않는다는 것입니다. 나는 **** 안드로이드가 왜 그렇게 구현해야했는지 모르겠다.
Hossain Khan

너비가 아닌 장치의 방향이 특별히 필요한 이유가 궁금합니다. 너비만으로 해결되지 않는 문제는 무엇입니까?
scurker

해상도가 다른 여러 장치로 작업하고 있습니다. 너비가 방향의 대안으로 어떻게 사용될 수 있는지 예를 들어 주시겠습니까? 방향 변경 사용에 대해 방향 변경에 여러 응용 프로그램이 있습니다. 일반적으로 사용 가능한 공간은 다른 방향으로 다릅니다. 따라서 일부 요소는 방향에 따라 숨기거나 크기를 조정할 수 있습니다. 모든 도움에 감사드립니다.
Hossain Khan

@HossainKhan @media all and (max-device-wdith:NNNpx){}또는 @media all and (min-device-wdith:NNNpx){}또는@media all and (device-wdith:NNNpx){}
RaphaelDDL

1
궁극적으로 and (orientation:portrait)최대 및 최소 너비 를 제거 하고 적용하여 내 문제를 해결했습니다. !!!
Libin

16

대안은를 사용할 수 있으며 device-aspect-ratio변경되지 않습니다. 그러나 Webkit에서 JavaScript 테스트가 새 종횡비에 대해 true를 반환하더라도 장치를 회전하면이 쿼리를 사용하여 CSS 규칙 업데이트가 트리거되지 않습니다. 이것은 명백하게 버그로 인해 ,하지만 난 버그 리포트를 찾을 수 없습니다입니다. 의 조합을 사용 orientation하고 {min,max}-device-aspect-ratio잘 작동 것 같다 :

@media screen and (max-device-aspect-ratio: 1/1) and (orientation: portrait)
@media screen and (min-device-aspect-ratio: 1/1) and (orientation: landscape)

orientation트리거 사용은 예상대로 업데이트되고 사용은 device-aspect-ratio실제 방향 변경으로 업데이트됩니다.


불행히도이 기능은 이제 더 이상 사용되지 않습니다. developer.mozilla.org/en-US/docs/Web/CSS/@media/…
Eugene Gluhotorenko

2020 년 중반이고 이것은 더 이상 사용되지 않음에도 불구하고 여전히 작동합니다 ... 훌륭한 솔루션, 내가 가진 모든 경우에서 실제로 나를 위해 일한 유일한 솔루션입니다!
qraqatit

6

나는 위에 나열된 옵션을 통해 작업했지만 나를 위해 문제를 해결하지 못했습니다. 나는 키보드 디스플레이 문제를 피하기 위해 일관된 높이 결과를 제공하기 때문에 screen.availHeight를 사용하도록 전환했습니다.

// Avoiding the keyboard in Android causing the portrait orientation to change to landscape. 
// Not an issue in IOS. Can use window.orientation.
var currentOrientation = function() {
  // Use screen.availHeight as screen height doesn't change when keyboard displays.  
  if(screen.availHeight > screen.availWidth){
    $("html").addClass('portrait').removeClass('landscape'); 
  } else {
    $("html").addClass('landscape').removeClass('portrait'); 
  }
}

// Set orientation on initiliasation
currentOrientation();
// Reset orientation each time window is resized. Keyboard opening, or change in orientation triggers this.
$(window).on("resize", currentOrientation);

그래서 저는 이것을 조금 더 테스트 해 왔으며 그렇게 간단하지 않습니다. Android 장치는 screen.availHeight 및 screen.availWidth를 사용해야합니다. IOS는 버그가 있지만 IOS에는 window.orientation을 사용하십시오. 데스크톱은 화면 크기가 아닌 창 크기를 원하므로 window.innerHeight, window.innerWidth를 사용해야합니다.
Robby Jennings 2012

나는 위의 코드를 사용하여 벽에 머리를 부딪혔다. 너무 까다 롭습니다. 이 앱은 데스크톱을 지원하지 않기 때문에 window.orientation을 사용하고 있습니다. Android 및 IOS 용 매직 솔루션입니다. 이제 잘 작동합니다. var orientation = Math.abs (window.orientation) === 90? 'landscape': '세로';
Robby Jennings 2012

3

나를 위해 이것은 트릭을했습니다.

  @media screen and (max-device-aspect-ratio: 1/1), (max-aspect-ratio: 1/1){
        /*Portrait Mode*/
};

max-aspect-ratio단순히 창 크기를 조정하여 세로 모드를 트리거 하는 동안 (PC 및 기타 가로 전용 장치에 유용), max-device-aspect-ratio스마트 폰 또는 다양한 방향의 기타 장치에 도움이됩니다. 가로 모드에 대한 특정 설정을 선언하지 않기 때문에 max-aspect-ratio시스템에 1보다 큰 값을보고 하더라도 max-device-aspect-ratioAndroid 기기가 그런 방향 으로 향하면 세로 모드가 계속 트리거됩니다 .

1/1부분은 기본적 그렇지 가로 모드로 진행 비율 <= 1 인 경우가 세로 모드로 진행한다는 것을 의미한다.


2
키보드가 나오면 어떨까요?
adi518

가상 키보드가 모바일 장치에 나타날 때 장치의 가로 세로 비율 (최대 장치 가로 세로 비율)은 실제로 장치를 회전하거나 의도적으로 화면 방향을 세로에서 가로로 또는 그 반대로 변경할 때만 변경되기 때문에 변경되지 않습니다. -반대.
helveciofneto

예, 결국 직접 구현하고 테스트했습니다. 나는 이것을 중심으로 패키지를 개발 중이다 : npmjs.com/package/mobile-orientation
adi518

한 가지 더 문의하기 위해 돌아 왔습니다 : (max-aspect-ratio: 1/1). 데스크톱에서 세로를 감지하는 데이 비트 만 필요한 것 같습니까?
adi518

권리. 1/1은 완벽한 사각형이 여전히 세로 모드를 트리거하도록하는 것입니다 (데스크톱의 브라우저 창과 같이 창 크기를 조정할 수있는 시스템에서 가능함). 그것 없이는이 정확한 비율로 이상한 일이 일어납니다.
helveciofneto

1

나는 위의 몇 가지 답변을 살펴 보았고 그중 어느 것도 내가 원하는대로, 즉 가능한 한 가깝게 iPhone 기능을 모방하지 못했습니다. 다음은 현재 프로덕션에서 나를 위해 일하는 것입니다.

나중에 확인할 수 있도록 장치 뷰포트의 창 너비와 높이를 데이터 속성에 할당하여 작동합니다. 전화기는 키보드를 들어 올릴 때 너비를 조정하지 않기 때문에 높이, 원래 너비에 대한 비율 및 너비를 확인해야만 키보드가 위로 올라 갔는지 알 수 있습니다. 아직 실패한 사용 사례를 찾지 못했지만 그럴 것이라고 확신합니다. 모두 찾으면 알려주세요.

js 전환에 사용되는 InitialRun 및 MobileOrientation과 같은 일부 전역을 사용하고 있으며 CSS 조작을 위해 DOM에 정보를 저장하기 위해 html5 데이터 속성을 사용하고 있습니다.

    var InitialRun = true; // After the initial bootstrapping, this is set to false;
    var MobileOrientation = 'desktop';
    function checkOrientation(winW, winH){ // winW and winH are the window's width and hieght, respectively
        if (InitialRun){
            if (winW > winH){
                $('body').attr('data-height',winW);
                $('body').attr('data-width',winH);
                MobileOrientation = 'landscape';    
                $('body').attr('data-orientation','landscape'); 
            }
            else{
                $('body').attr('data-height',winH);
                $('body').attr('data-width',winW);
                MobileOrientation = 'portrait';
                $('body').attr('data-orientation','portrait');
            }
        }
        else{
            if (winW > winH && winW != $('body').data('width')){
                MobileOrientation = 'landscape';    
                $('body').hdata('orientation','landscape'); //TODO:uncomment
                $('body, #wrapper').css({'height':"100%",'overflow-y':'hidden'});
                //$('body').attr('data-orientation','portrait');
            }
            else{
                MobileOrientation = 'portrait';
                $('body').attr('data-orientation','portrait');
                $('body, #wrapper').css({'height':$('body').data('height'),'overflow-y':'auto'});
            }
        }

    }

1

이 문제를 해결하기 위해 간단한 트릭을 사용했습니다.

@media (max-width: 896px) and (min-aspect-ratio: 13/9){/* Landscape content*/}

최대 너비 : 896px는 모든 모바일 장치에 사용할 수 있습니다. 이 솔루션을 사용해보십시오!


당신은 내 하루를 저장합니다 :), 그러나 그것이 가로에서 세로로 돌아올 때, 이것을 처리하는 방법은 페이지의 확대가 깨졌습니다.
아미르 Farahani

이것은 현재 모바일 장치의 최대 너비에 의존하며 기술을 개선 할 때 변경됩니다. 그렇다면 모든 미디어 쿼리 시나리오를 변경해야합니까? 나는 이것이 좋지 않은 생각이라고 생각합니다.
QMaster 2010 년


0

아이디어 : 미디어 쿼리에서 세로 매개 변수를 제거하고 최소 너비 만 남겨 둡니다. 해당 미디어 쿼리에서 세로 모드에 대한 일반적인 스타일을 지정하십시오. 그런 다음 키보드가 표시 될 때 브라우저가 해당 쿼리를 사용하지 않도록 최소 높이로 가로 모드에 대한 다른 미디어 쿼리를 만듭니다. 이 '충분한 최소 높이'가 무엇인지 실험해야하지만, 대부분의 가로 모드는 키보드가 튀어 나올 때보 다 높이가 높기 때문에 너무 어렵지는 않습니다. 또한 세로보기에서 대부분의 스마트 폰 (예 : 약 400px)보다 큰 가로 쿼리에 '최소 너비'를 추가하여 쿼리 범위를 제한 할 수 있습니다.

다음은 대안 (그리고 빈약 한) 솔루션입니다.-세로 모드 이외의 다른 모든 항목에서 'display : none'이있는 빈 임의 요소를 html에 추가합니다. -input : focus에 대한 jquery 또는 javascript listener를 만듭니다. 입력을 클릭하면 자바 스크립트가 임의 요소의 표시 속성을 확인합니다. 'block'을 반환하거나 세로 모드 중에 설정 한 모든 항목을 반환하면 JS로 스타일을 세로 모드 쿼리로 재정의 할 수 있습니다. 반대로 하드 코딩 한 요소의 style.cssText 속성을 비우기위한 input : blur 리스너가 있습니다.

저는 지금 직접 이것을 실험하고 있습니다. 견고하고 관리하기 쉬운 것을 얻을 때 작동하는 코드를 게시 할 것입니다. (내 첫 번째 해결책이 가장 합리적인 것 같습니다).


0

이것은 나를 위해 안정적으로 작동합니다. 내가 사용하고 http://detectmobilebrowsers.com/을 $ .browser.mobile를 검출하기 위해 jQuery를 확장하십시오.

if ($.browser.mobile) {
  var newOrientationPortrait = true;

//Set orientation based on height/width by default
  if ($(window).width() < $(window).height())
      newOrientationPortrait = true;
  else
      newOrientationPortrait = false;

//Overwrite orientation if mobile browser supports window.orientation
if (window.orientation != null)
    if (window.orientation === 0)
        newOrientationPortrait = true;
    else
        newOrientationPortrait = false;

방향에 따라 뷰포트를 수정하는 코드는 다음과 같습니다. 이 기능은 태블릿이 아닌 모바일 장치에서만 호출됩니다. 이를 통해 400px 및 800px (Portrait vs Landscape) 용 CSS를 쉽게 작성할 수 있습니다.

_onOrientationChange = function() {
    if (_orientationPortrait) 
        $("meta[name=viewport]").attr("content", "width=400,user-scalable=no");
    else 
        $("meta[name=viewport]").attr("content", "width=800");
}

내 요구 사항의 특성으로 인해 DOM 자체가 방향에 따라 변경되어야했기 때문에 CSS 미디어 쿼리에서만이 작업을 수행 할 수 없었습니다. 불행히도 제 직장에서 사업가들은 먼저 개발 컨설팅없이 소프트웨어 요구 사항을 작성합니다.


0

나는 iPad에서 똑같은 문제에 직면했습니다.
즉; 소프트 키보드가 세로 모드로 나타나면 장치가 가로 방향으로 감지되고 가로 스타일이 화면에 적용되어 화면이 엉망이됩니다.

장치 사양

  • 장치 : iPad Mini 4
  • 운영체제 : iOS 11.2.6
  • 화면 해상도 : 1024 x 768

안타깝게도이 솔루션은 효과가 없었습니다.

@media screen and (min-aspect-ratio: 13/9) { /* landscape styles here */}
@media screen and (max-aspect-ratio: 13/9) { /* portrait styles here */}

그래서 제가 한 것은 초상화 모드에 대해 이와 같은 미디어 쿼리를 작성했습니다.

@media only screen and (min-width : 300px) and (max-width : 768px) and (orientation : landscape) {
/* portrait styles, when softkeyboard appears, goes here */
}

즉; 소프트 키보드가 나타나면 화면 높이는 줄어들지 만 화면 너비는 768px로 유지되어 미디어 쿼리가 화면을 가로 방향으로 감지합니다. 따라서 위와 같이 주어진 작업.


0

iPhone 11 Pro Max 뷰포트는 414 x 896 PX이므로 방향 : 최소 너비의 가로 : 500px로 충분해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.