web-dev-qa-db-fra.com

Insérer CSS dans le code HTML chargé dans UIWebView/WKWebView

Je parviens à obtenir du contenu HTML et à l'afficher dans mon UIWebView. 

Mais voulez personnaliser le contenu en ajoutant un fichier CSS externe. Je ne peux que changer la taille du texte et de la police. J'ai essayé toutes les solutions possibles pour apporter des modifications, mais cela ne fonctionne pas - il ne montre aucun changement. 

Ci-dessous mon code

HTMLNode* body = [parser body];
HTMLNode* mainContentNode = [body  findChildWithAttribute:@"id" matchingName:@"main_content" allowPartial:NO];
NSString *pageContent = [NSString stringWithFormat:@"%@%@", cssString, contentHtml];
        [webView loadHTMLString:pageContent baseURL:[NSURL URLWithString:@"http://www.example.org"]];

-(void)webViewDidFinishLoad:(UIWebView *)webView1{
    int fontSize = 50;
    NSString *font = [[NSString alloc] initWithFormat:@"document.getElementsByTagName('body')[0].style.webkitTextSizeAdjust= '%d%%'", fontSize];
    NSString *fontString = [[NSString alloc] initWithFormat:@"document.getElementById('body').style.fontFamily=\"helvetica\""];

    [webView1 stringByEvaluatingJavaScriptFromString:fontString];
    [webView1 stringByEvaluatingJavaScriptFromString:font];
}

Aidez-moi, s'il vous plaît, à obtenir la feuille de style css.

25
cole

Vous pouvez le faire comme ça:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    NSString *cssString = @"body { font-family: Helvetica; font-size: 50px }"; // 1
    NSString *javascriptString = @"var style = document.createElement('style'); style.innerHTML = '%@'; document.head.appendChild(style)"; // 2
    NSString *javascriptWithCSSString = [NSString stringWithFormat:javascriptString, cssString]; // 3
    [webView stringByEvaluatingJavaScriptFromString:javascriptWithCSSString]; // 4
}

Ce que fait ce code:

// 1: définit une chaîne contenant toutes les déclarations CSS

// 2: Définissez une chaîne javascript qui crée un nouvel élément HTML DOM <style> et insère les déclarations CSS dans celui-ci. En réalité, l’insertion est faite à l’étape suivante. Pour l’instant, il n’ya que l’espace réservé %@. J'ai fait cela pour éviter que la ligne ne devienne trop longue, mais les étapes 2 et 3 pourraient être effectuées ensemble.

// 3: combinez les 2 chaînes

// 4: Exécuter le javascript dans le UIWebView

Pour que cela fonctionne, votre code HTML doit comporter un élément <head></head>

MODIFIER:

Vous pouvez également charger la chaîne css à partir d'un fichier css local (nommé "styles.css" dans ce cas). Il suffit de remplacer l'étape // 1 par ce qui suit:

NSString *path = [[NSBundle mainBundle] pathForResource:@"styles" ofType:@"css"];
NSString *cssString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];

Une autre option consiste simplement à injecter un élément <link> dans le <head> qui charge le fichier CSS:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    NSString *path = [[NSBundle mainBundle] pathForResource:@"styles" ofType:@"css"];
    NSString *javascriptString = @"var link = document.createElement('link'); link.href = '%@'; link.rel = 'stylesheet'; document.head.appendChild(link)";
    NSString *javascriptWithPathString = [NSString stringWithFormat:javascriptString, path];
    [webView stringByEvaluatingJavaScriptFromString:javascriptWithPathString];
}

Cette solution fonctionne mieux pour les gros fichiers CSS. Malheureusement, cela ne fonctionne pas avec les fichiers HTML distants. Vous ne pouvez l'utiliser que lorsque vous souhaitez insérer du CSS dans du HTML que vous avez téléchargé sur votre application.

MISE À JOUR: WKWebView/Swift 3.x

Lorsque vous travaillez avec un WKWebView, l'injection d'un élément <link> ne fonctionne pas à cause des paramètres de sécurité de WKWebView.

Vous pouvez toujours injecter le css sous forme de chaîne. Créez la chaîne CSS dans votre code //1 ou placez-la dans un fichier local //2. Sachez simplement qu'avec WKWebView vous devez faire l'injection dans la méthode WKNavigationDelegate's webView(_:didFinish:):

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    insertCSSString(into: webView) // 1
    // OR
    insertContentsOfCSSFile(into: webView) // 2
}

func insertCSSString(into webView: WKWebView) {
    let cssString = "body { font-size: 50px; color: #f00 }"
    let jsString = "var style = document.createElement('style'); style.innerHTML = '\(cssString)'; document.head.appendChild(style);"
    webView.evaluateJavaScript(jsString, completionHandler: nil)
}

func insertContentsOfCSSFile(into webView: WKWebView) {
    guard let path = Bundle.main.path(forResource: "styles", ofType: "css") else { return }
    let cssString = try! String(contentsOfFile: path).trimmingCharacters(in: .whitespacesAndNewlines)
    let jsString = "var style = document.createElement('style'); style.innerHTML = '\(cssString)'; document.head.appendChild(style);"
    webView.evaluateJavaScript(jsString, completionHandler: nil)
}
46
joern

Puisque UIWebView est obsolète dans iOS 12, je ne répondrai que pour WKWebView. J'ai implémenté le chargement CSS comme il était décrit dans la réponse acceptée. Le problème était que parfois la transition du HTML sans CSS appliqué au HTML avec CSS était visible.
Je pense qu’une meilleure approche consiste à utiliser la WKUserScript pour injecter le CSS comme ceci: 

lazy var webView: WKWebView = {
    guard let path = Bundle.main.path(forResource: "style", ofType: "css") else {
        return WKWebView()
    }

    let cssString = try! String(contentsOfFile: path).components(separatedBy: .newlines).joined()
    let source = """
      var style = document.createElement('style');
      style.innerHTML = '\(cssString)';
      document.head.appendChild(style);
    """

    let userScript = WKUserScript(source: source,
                                  injectionTime: .atDocumentEnd,
                                  forMainFrameOnly: true)

    let userContentController = WKUserContentController()
    userContentController.addUserScript(userScript)

    let configuration = WKWebViewConfiguration()
    configuration.userContentController = userContentController

    let webView = WKWebView(frame: .zero,
                            configuration: configuration)
    return webView
}()

Vous pouvez en savoir plus sur cette approche dans cet article blog .

4
Amer Hukic

Au lieu d'appliquer css avec une balise style, il vaut mieux l'appliquer avec la balise link:

func insertContentsOfCSSFile2(into webView: WKWebView) {
    guard let path = Bundle.main.path(forResource: "resource", ofType: "css") else { return }                
    let csFile = "var head = document.getElementsByTagName('head')[0];var link = document.createElement('link'); link.rel = 'stylesheet';link.type = 'text/css';link.href = '\(path)';link.media = 'all';head.appendChild(link);"

    webView.evaluateJavaScript(csFile) {(result, error) in
        if let error = error {
            print(error)
        }
    }
}

Je l'ai testé. ça marche bien.

1
VIJAY SINGH RAGHAV

Voir la réponse acceptée de @ joern pour plus de détails. J'ajoute cette réponse parce que je me suis heurté à un cas étrange de Edge. Mon cas d'utilisation particulier nécessitait d'ajouter du style à une div avec un class="dialog". Pour une raison quelconque, les styles utilisant .dialog et div ne fonctionnaient pas, alors que d'autres types de styles fonctionnaient. En fin de compte, j’ai utilisé ce qui suit pour définir la largeur de la dialog

let width = Int(webView.bounds.width)
let script = "document.getElementsByClassName(\"dialog\")[0].style.width = \"\(width)px\""
webView.evaluateJavaScript(script)
0
SuperGuyAbe